본문 바로가기

Develop/Coding Test

코딩테스트 입문 (feat. Day 15 문자열, 해시, 배열, 수학)

15일차 스탬프

1.  영어가 싫어요

Q. 영어가 싫은 머쓱이는 영어로 표기되어있는 숫자를 수로 바꾸려고 합니다. 문자열 numbers가 매개변수로 주어질 때, numbers를 정수로 바꿔 return 하도록 solution 함수를 완성해 주세요.

func solution(_ numbers:String) -> Int64 {
    var result: String = numbers
        .replacingOccurrences(of: "zero", with: "0")
        .replacingOccurrences(of: "one", with: "1")
        .replacingOccurrences(of: "two", with: "2")
        .replacingOccurrences(of: "three", with: "3")
        .replacingOccurrences(of: "four", with: "4")
        .replacingOccurrences(of: "five", with: "5")
        .replacingOccurrences(of: "six", with: "6")
        .replacingOccurrences(of: "seven", with: "7")
        .replacingOccurrences(of: "eight", with: "8")
        .replacingOccurrences(of: "nine", with: "9")
    return Int64(result)!
}

 

A. replacingOccurrences(of:with:)를 활용해 전달 받은 numbers의 영어를 숫자로 변경한 문자열을

Int64로 형변환한 후 반환하여 해결했다.

2. 인덱스 바꾸기

Q. 문자열 my_string과 정수 num1, num2가 매개변수로 주어질 때, my_string에서 인덱스 num1과 인덱스 num2에 해당하는 문자를 바꾼 문자열을 return 하도록 solution 함수를 완성해보세요.

func solution(_ my_string:String, _ num1:Int, _ num2:Int) -> String {
    var result = my_string.map {String($0)}
    let temp = result[num1]
    result[num1] = result[num2]
    result[num2] = temp
    return result.joined()
}

 

A. 먼저 전달 받은 my_string을 고차함수 map을 활용해 한자리씩 배열로 쪼갠다.

그 후, 임시값에 result[num1]에 해당하는 문자를 저장한 후, result[num1] 값을 result[num2] 값으로 변경한다.

그리고 result[num2]을 저장한 임시값으로 변경한 후, joined()를 활용해 result를 문자열로 변환한 후 반환하여 해결했다.

 

feat.

func solution(_ myString: String, _ num1: Int, _ num2: Int) -> String {
    var array = ArraySlice(myString)

    array.swapAt(num1, num2)
    return array.map { String($0) }.joined()
}

 

다른 풀이를 보았을 때, swapAt()이란 메서드를 처음 알게 되었다.

컬렉션에서 첫 번째 index와 두 번째 index의 값을 바꾸는 메서드인데

다른 문제를 해결할 때, 알아두고 있으면 유용하게 사용될 것 같다!

3. 한 번만 등장한 문자

Q. 문자열 s가 매개변수로 주어집니다. s에서 한 번만 등장하는 문자를 사전 순으로 정렬한 문자열을 return 하도록 solution 함수를 완성해보세요. 한 번만 등장하는 문자가 없을 경우 빈 문자열을 return 합니다.

func solution(_ s:String) -> String {
    var result: [String] = []
    var duplic: [String] = []
    s.forEach {
        if result.contains(String($0)) {
            duplic.append(String($0))
        } else {
            result.append(String($0))
        }
    }
    result.removeAll { duplic.contains($0) }
    return result.sorted().joined()
}

 

A. 전달 받은 s를 forEach문으로 순회하면서

만약 해당 원소가 result에 포함되면 duplic 배열에 추가하고 포함되지 않으면 result 배열에 추가한다.

그리고 result 배열에 여러 번 등장한 문자를 제거하기 위해 removeAll을 활용해 duplic에 포함된 원소들을 제거한다.

마지막으로 result를 sorted()를 통해 사전 순으로 정렬한 후, joined()를 활용해 문자열로 반환하여 해결했다.

4. 약수 구하기

Q. 정수 n이 매개변수로 주어질 때, n의 약수를 오름차순으로 담은 배열을 return하도록 solution 함수를 완성해주세요.

func solution(_ n:Int) -> [Int] {
    var result: [Int] = [1]
    if n == 1 {
        return result
    }
    (2...n / 2).forEach {
        if n % $0 == 0 {
            result.append($0)
         }
    }
    result.append(n)
    return result
}

 

A. 먼저, 1의 약수는 1이기 때문에 전달 받은 n이 1일 경우 1을 담은 result를 반환한다.

그 후, 2부터 n을 2로 나눈 값까지 forEach로 순회하면서 n을 순회하는 값으로 나눴을 때,

나머지가 0이면 약수로 판별할 수 있기 때문에 result에 추가한다.

반복문이 끝나면 n의 약수에는 n도 포함되기 때문에 result에 n을 추가한 후,

지금까지 오름차순으로 약수를 result에 저장했기 때문에 result 바로 반환하여 해결했다.

 

feat.

func solution(_ n: Int) -> [Int] { (1...n).filter { n % $0 == 0 } }

 

다른 풀이를 보았는데, filter를 활용해 간단하게 해결한 풀이를 보았다.

내가 작성한 풀이와 비교했을 때, 위 풀이가 코드적으로는 간단하지만

만약 n이 엄청 큰 수라면 위 풀이는 1부터 n까지를 순회해야한다.

하지만 내 풀이는 그 절반인 n / 2까지만 순회하면 되기 때문에 동작 속도에서 차이가 날 수 있을 것이다.

 

그리고 갑자기 더 효율적인 코드를 짜려면 어떻게 해야할 지 궁금해져서

ChatGPT에 물어본 결과, 다음과 같은 코드를 얻을 수 있었다.

func solution(_ n: Int) -> [Int] {
    var result: [Int] = []
    for i in 1...Int(Double(n).squareRoot()) {
        if n % i == 0 {
            result.append(i)
            if i != n / i {
                result.append(n / i)
            }
        }
    }
    return result.sorted()
}

 

위 코드를 통해서는 앞선 두 풀이와 다르게 1부터 √n까지만 순회하기 때문에

시간 복잡도가 O(√n)으로 코드를 더 효율적으로 개선할 수 있게 된다.


오늘은 시간복잡도를 고려해 효율적으로 코드를 작성하는 방법을 생각해보았는데

앞으로도 위 내용들을 고려한다면 문제 풀이가 조금 더 유의미한 시간이 될 수 있을 것 같다ㅎㅎ

내일도 화이팅!