문제

두 자연수 A와 B에 대해서, A의 배수이면서 B의 배수인 자연수를 A와 B의 공배수라고 한다. 이런 공배수 중에서 가장 작은 수를 최소공배수라고 한다. 예를 들어, 6과 15의 공배수는 30, 60, 90등이 있으며, 최소 공배수는 30이다.

두 자연수 A와 B가 주어졌을 때, A와 B의 최소공배수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 T(1 ≤ T ≤ 1,000)가 주어진다. 둘째 줄부터 T개의 줄에 걸쳐서 A와 B가 주어진다. (1 ≤ A, B ≤ 45,000)

출력

첫째 줄부터 T개의 줄에 A와 B의 최소공배수를 입력받은 순서대로 한 줄에 하나씩 출력한다.

풀이

유클리드 호제법 이용해서 구한다

 

import Foundation

func gcd(num1: Int, num2: Int) -> Int {
    if num2 == 0 {
        return num1
    } else {
        return gcd(num1: num2, num2: num1 % num2)
    }
}

let count = Int(readLine()!)!

for i in 0..<count {
    var nums = readLine()!.split(separator: " ").map{ Int(String($0))!}
    if nums[0] > nums[1] {
        print(nums[0] * nums[1] / gcd(num1: nums[0], num2: nums[1]))
    } else {
        print(nums[0] * nums[1] / gcd(num1: nums[1], num2: nums[0]))
    }
}

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-1735 분수 합 Swift  (0) 2023.04.07
BOJ-13241 최소공배수 Swift  (0) 2023.04.07
BOJ-11478 서로 다른 부분 문자열의 개수 Swift  (0) 2023.04.07
BOJ-1269 대칭 차집합 Swift  (0) 2023.04.06
BOJ-1764 듣보잡 Swift  (0) 2023.04.06

최대공약수 GCD

두 자연수의 공통된 약수 중 가장 큰 수

ex) 30 과 45 의 최대공약수는 15

 

최소공배수 LCM

두 자연수의 공통된 배수 중 가장 작은 수

최소공배수 = 두 자연수의 곱 / 최대공약수

ex) 6과 10의 최소공배수는 30

 

 

유클리드 호제법

2개의 자연수 a,b에 대해 (a > b) a를 b로 나눈 나머지를 r이라 하면

a와 b의 최대공약수는 b와 r의 최대공약수와 같다

이 성질을 이용해,

b를 r로 나눈 나머지를 r0라 하고, r을 r0으로 나누는 과정을 반복해서 나머지가 0일때 

나눈수가 a와 b의 최대공약수가 된다. 

 

func gcd(num1: Int, num2: Int) -> Int {
    if num2 == 0 {
        return num1
    } else {
        return gcd(num1: num2, num2: num1 % num2)
    }
}

시간복잡도: O(logN)

문제

문자열 S가 주어졌을 때, S의 서로 다른 부분 문자열의 개수를 구하는 프로그램을 작성하시오.

부분 문자열은 S에서 연속된 일부분을 말하며, 길이가 1보다 크거나 같아야 한다.

예를 들어, ababc의 부분 문자열은 a, b, a, b, c, ab, ba, ab, bc, aba, bab, abc, abab, babc, ababc가 있고, 서로 다른것의 개수는 12개이다.

입력

첫째 줄에 문자열 S가 주어진다. S는 알파벳 소문자로만 이루어져 있고, 길이는 1,000 이하이다.

출력

첫째 줄에 S의 서로 다른 부분 문자열의 개수를 출력한다.

풀이

1. 문자의 부분문자열을 Set에 저장

2. Set.count 출력

 

import Foundation

var strArr = readLine()!.map{String($0)}
var strSet = Set<String>()

for i in 0..<strArr.count {
    var str = ""
    for j in i..<strArr.count {
        str = str + strArr[j]
        strSet.insert(str)
    }
}
print(strSet.count)

 

 

 

 

<시간초과>

import Foundation

var str = readLine()!.map{String($0)}
var strSet = Set<String>()
var length = 0

for i in 0..<str.count {
    var count = str.count - i
    for j in 0..<count {
        let str = str[j...j+length].joined(separator: "")
        strSet.insert(str)
    }
    length += 1
}
print(strSet.count)

 

처음 시간초과가 났을때 부분문자열을 만드는 과정이 문제라 생각했었다

부분문자열의 길이를 1씩 증가시켜 각 인덱스마다 부분문자열을 추출하는 방식을 사용했다가,

더 간단하게 부분문자열을 추출하는 방법이 있어서 그 방법을 사용했지만

둘 다 2중 for문을 사용해서 결국 O(n^2) 라 생각한다

아마 문제는 배열에서 범위 추출하는 과정이 문제라 생각이 든다

배열에 대해서 따로 정리를 해봐야겠다

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-13241 최소공배수 Swift  (0) 2023.04.07
BOJ-1934 최소공배수 Swift  (0) 2023.04.07
BOJ-1269 대칭 차집합 Swift  (0) 2023.04.06
BOJ-1764 듣보잡 Swift  (0) 2023.04.06
BOJ-10816 숫자카드 2 Swift  (0) 2023.04.06

문제

자연수를 원소로 갖는 공집합이 아닌 두 집합 A와 B가 있다. 이때, 두 집합의 대칭 차집합의 원소의 개수를 출력하는 프로그램을 작성하시오. 두 집합 A와 B가 있을 때, (A-B)와 (B-A)의 합집합을 A와 B의 대칭 차집합이라고 한다.

예를 들어, A = { 1, 2, 4 } 이고, B = { 2, 3, 4, 5, 6 } 라고 할 때,  A-B = { 1 } 이고, B-A = { 3, 5, 6 } 이므로, 대칭 차집합의 원소의 개수는 1 + 3 = 4개이다.

입력

첫째 줄에 집합 A의 원소의 개수와 집합 B의 원소의 개수가 빈 칸을 사이에 두고 주어진다. 둘째 줄에는 집합 A의 모든 원소가, 셋째 줄에는 집합 B의 모든 원소가 빈 칸을 사이에 두고 각각 주어진다. 각 집합의 원소의 개수는 200,000을 넘지 않으며, 모든 원소의 값은 100,000,000을 넘지 않는다.

출력

첫째 줄에 대칭 차집합의 원소의 개수를 출력한다.

 

입력

1. 각 집합을 Set에 저장한다

2. Set.subtracting 으로 차집합을 구한다

3. 각각 구해진 차집합을 합한다 union

 

 

import Foundation

let counts = readLine()!.split(separator: " ").map{ Int(String($0))! }
var set1 = Set(readLine()!.split(separator: " ").map{Int(String($0))!})
var set2 = Set(readLine()!.split(separator: " ").map{Int(String($0))!})

var subSet1 = set1.subtracting(set2)
var subSet2 = set2.subtracting(set1)

print(subSet1.union(subSet2).count)

문제

김진영이 듣도 못한 사람의 명단과, 보도 못한 사람의 명단이 주어질 때, 듣도 보도 못한 사람의 명단을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 듣도 못한 사람의 수 N, 보도 못한 사람의 수 M이 주어진다. 이어서 둘째 줄부터 N개의 줄에 걸쳐 듣도 못한 사람의 이름과, N+2째 줄부터 보도 못한 사람의 이름이 순서대로 주어진다. 이름은 띄어쓰기 없이 알파벳 소문자로만 이루어지며, 그 길이는 20 이하이다. N, M은 500,000 이하의 자연수이다.

듣도 못한 사람의 명단에는 중복되는 이름이 없으며, 보도 못한 사람의 명단도 마찬가지이다.

출력

듣보잡의 수와 그 명단을 사전순으로 출력한다.

풀이

1. N개 이름을 set에 저장하고, M개 이름을 set에 저장

2. 두개의 Set의 교집합 출력

 

import Foundation

let inputs = readLine()!.split(separator: " ").map{ Int(String($0))!}
var set1 = Set<String>()
var set2 = Set<String>()

for i in 0..<inputs[0] {
    set1.insert(readLine()!)
}
for i in 0..<inputs[1] {
    set2.insert(readLine()!)
}
var result = set1.intersection(set2).sorted{ $0 < $1}
print(result.count)
for i in result {
    print(i)
}

문제

숫자 카드는 정수 하나가 적혀져 있는 카드이다. 상근이는 숫자 카드 N개를 가지고 있다. 정수 M개가 주어졌을 때, 이 수가 적혀있는 숫자 카드를 상근이가 몇 개 가지고 있는지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 정수가 주어진다. 숫자 카드에 적혀있는 수는 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다.

셋째 줄에는 M(1 ≤ M ≤ 500,000)이 주어진다. 넷째 줄에는 상근이가 몇 개 가지고 있는 숫자 카드인지 구해야 할 M개의 정수가 주어지며, 이 수는 공백으로 구분되어져 있다. 이 수도 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다.

출력

첫째 줄에 입력으로 주어진 M개의 수에 대해서, 각 수가 적힌 숫자 카드를 상근이가 몇 개 가지고 있는지를 공백으로 구분해 출력한다.

풀이

1. 소지하고 있는 숫자와 숫자의 갯수를 Dictionary에 저장

2. 주어진 숫자배열을 Dictionary에 대입 후 출력

 

import Foundation

let num = Int(readLine()!)!
var cards = readLine()!.split(separator: " ").map{ Int(String($0))! }
var dict = [Int: Int]()

let getNum = Int(readLine()!)!
var getCards = readLine()!.split(separator: " ").map{ Int(String($0))! }

for i in cards {
    if dict[i] == nil {
        dict[i] = 1
    } else {
        dict[i] = dict[i]! + 1
    }
}

print(getCards.map{ (num: Int) -> String in
    if dict[num] == nil {
        return "0"
    } else {
        return "\(dict[num]!)"
    }
}.joined(separator: " "))

입력

첫째 줄에는 도감에 수록되어 있는 포켓몬의 개수 N이랑 내가 맞춰야 하는 문제의 개수 M이 주어져. N과 M은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수인데, 자연수가 뭔지는 알지? 모르면 물어봐도 괜찮아. 나는 언제든지 질문에 답해줄 준비가 되어있어.

둘째 줄부터 N개의 줄에 포켓몬의 번호가 1번인 포켓몬부터 N번에 해당하는 포켓몬까지 한 줄에 하나씩 입력으로 들어와. 포켓몬의 이름은 모두 영어로만 이루어져있고, 또, 음... 첫 글자만 대문자이고, 나머지 문자는 소문자로만 이루어져 있어. 아참! 일부 포켓몬은 마지막 문자만 대문자일 수도 있어. 포켓몬 이름의 최대 길이는 20, 최소 길이는 2야. 그 다음 줄부터 총 M개의 줄에 내가 맞춰야하는 문제가 입력으로 들어와. 문제가 알파벳으로만 들어오면 포켓몬 번호를 말해야 하고, 숫자로만 들어오면, 포켓몬 번호에 해당하는 문자를 출력해야해. 입력으로 들어오는 숫자는 반드시 1보다 크거나 같고, N보다 작거나 같고, 입력으로 들어오는 문자는 반드시 도감에 있는 포켓몬의 이름만 주어져. 그럼 화이팅!!!

출력

첫째 줄부터 차례대로 M개의 줄에 각각의 문제에 대한 답을 말해줬으면 좋겠어!!!. 입력으로 숫자가 들어왔다면 그 숫자에 해당하는 포켓몬의 이름을, 문자가 들어왔으면 그 포켓몬의 이름에 해당하는 번호를 출력하면 돼. 그럼 땡큐~

이게 오박사님이 나에게 새로 주시려고 하는 도감이야. 너무 가지고 싶다ㅠㅜ. 꼭 만점을 받아줬으면 좋겠어!! 파이팅!!!

풀이

1. Dictionary에 포켓몬번호와 이름 저장

2. Array에 포켓몬번호 index에 맞게 이름 저장

3. 포켓몬이름이 주어지면 Dictionary에서 value, 번호가 주어지면 Array에서 출력

 

Dictionary 단일로 저장하고 filter를 이용해 key값을 불러왔는데 시간초과가 떴다

더 줄이는 방법으로 아예 두가지 컬렉션으로 접근하는 방식을 이용했다

 

import Foundation

let inputs = readLine()!.split(separator:" ").map{ Int(String($0))!}
var pokemonsDict = [String: Int]()
var pokemonsArr = Array(repeating: "", count: inputs[0]+1)

for i in 1...inputs[0] {
    let pokemon = readLine()!
    pokemonsDict[pokemon] = i
    pokemonsArr[i] = pokemon
}

for j in 0..<inputs[1] {
    var quest = readLine()!

    if Int(quest) == nil {
        print(pokemonsDict[quest]!)
    } else {
        print(pokemonsArr[Int(quest)!])
    }
}

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-1764 듣보잡 Swift  (0) 2023.04.06
BOJ-10816 숫자카드 2 Swift  (0) 2023.04.06
BOJ-7785 회사에 있는 사람 Swift  (0) 2023.04.06
BOJ-14425 문자열 집합 Swift  (0) 2023.04.06
BOJ-10815 숫자 카드 Swift  (0) 2023.04.06

문제

상근이는 세계적인 소프트웨어 회사 기글에서 일한다. 이 회사의 가장 큰 특징은 자유로운 출퇴근 시간이다. 따라서, 직원들은 반드시 9시부터 6시까지 회사에 있지 않아도 된다.

각 직원은 자기가 원할 때 출근할 수 있고, 아무때나 퇴근할 수 있다.

상근이는 모든 사람의 출입카드 시스템의 로그를 가지고 있다. 이 로그는 어떤 사람이 회사에 들어왔는지, 나갔는지가 기록되어져 있다. 로그가 주어졌을 때, 현재 회사에 있는 모든 사람을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 로그에 기록된 출입 기록의 수 n이 주어진다. (2 ≤ n ≤ 106) 다음 n개의 줄에는 출입 기록이 순서대로 주어지며, 각 사람의 이름이 주어지고 "enter"나 "leave"가 주어진다. "enter"인 경우는 출근, "leave"인 경우는 퇴근이다.

회사에는 동명이인이 없으며, 대소문자가 다른 경우에는 다른 이름이다. 사람들의 이름은 알파벳 대소문자로 구성된 5글자 이하의 문자열이다.

출력

현재 회사에 있는 사람의 이름을 사전 순의 역순으로 한 줄에 한 명씩 출력한다.

풀이

1. 출입 기록 순서대로 주어지는 n개의 이름과 기록을 Dictionary에 저장 및 출입자 이름을 Set에 저장

2. Set에 저장된 출입자들 중 Dictionary에 대입해 "enter" 상태인 출입자들만 출력

 

import Foundation

let num = Int(readLine()!)!
var enterPersonDict = [String: String]()
var enteredPersonSet = Set<String>()

for i in 0..<num {
    let inputs = readLine()!.split(separator: " ").map{String($0)}
    enteredPersonSet.insert(inputs[0])
    enterPersonDict[inputs[0]] = inputs[1]
}

print(enteredPersonSet.filter{ enterPersonDict[$0] == "enter"}.sorted{ $0 > $1}.joined(separator: " "))

+ Recent posts