ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로그래머스] 가장 큰 수 / Swift
    프로그래밍/코딩테스트 2021. 5. 22. 14:02

    [문제 보기]

    더보기

    0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수를 알아내 주세요.

    예를 들어, 주어진 정수가 [6, 10, 2]라면 [6102, 6210, 1062, 1026, 2610, 2106]를 만들 수 있고, 이중 가장 큰 수는 6210입니다.

     

    0 또는 양의 정수가 담긴 배열 numbers가 매개변수로 주어질 때, 순서를 재배치하여 만들 수 있는 가장 큰 수를 문자열로 바꾸어 return 하도록 solution 함수를 작성해주세요.

     

    제한 사항

    • numbers의 길이는 1 이상 100,000 이하입니다.
    • numbers의 원소는 0 이상 1,000 이하입니다.
    • 정답이 너무 클 수 있으니 문자열로 바꾸어 return 합니다.

    입출력 예

    numbers, return
    [6, 10, 2] "6210"
    [3, 30, 34, 5, 9] "9534330"

    https://programmers.co.kr/learn/courses/30/lessons/42746

     

    코딩테스트 연습 - 가장 큰 수

    0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수를 알아내 주세요. 예를 들어, 주어진 정수가 [6, 10, 2]라면 [6102, 6210, 1062, 1026, 2610, 2106]를 만들 수 있고, 이중 가장 큰

    programmers.co.kr

     


    풀이 과정

    정렬 기준은 배열을 순회할 때 나오는 원소들을 붙여서 비교하는 것으로 정했다.

    예를들면, 0번째 인덱스에 12가 1번째 인덱스에 22가 들어있다면 0번째 인덱스 + 1번째 인덱스 이렇게 나열한 문자열은 1222가 될 것이고 거꾸로 1번째 인덱스 + 0번째 인덱스로 나열한 문자열은 2212가 될 것이다. 이렇게 각 붙인 문자열을 비교하여 내림차순으로 정렬했다.

     

    // 제자리 삽입 정렬로 구현한 버전
    import Foundation
    
    func solution(_ numbers:[Int]) -> String {
        var result = numbers
        
        for i in (0..<numbers.count) {
            let tmp = result[i]
            var current = 0
            
            for j in (0..<i) {
                current = i - j - 1
                let s1 = String(result[current])
                let s2 = String(tmp)
                
                if s1 + s2 > s2 + s1 {
                    current += 1
                    break
                }
                
                result[current + 1] = result[current]
            }
            
            result[current] = tmp
        }
        
        return result.reduce("") { $0 + String($1) }
    }

     

    처음에 구현했을 때 제자리 삽입 정렬로 구현했지만 역시나 시간초과 + 케이스 11번 틀림이 떴다 ㅠ

    정렬하는 부분을 기본 내장 sort로 바꾸고 다시 돌리니,

    // 내장 sort로 바꾼 버전
    import Foundation
    
    func solution(_ numbers:[Int]) -> String {
        return numbers.sorted {
            let s1 = String($0)
            let s2 = String($1)
            return s1 + s2 > s2 + s1
        }.reduce("") { $0 + String($1) } // 이 부분
    }

    시간 초과는 해결되었다. 문제 조건을 다시 제대로 읽어보니 0이 들어오는 경우를 생각해보지 않았다. 

    그래서 Int배열에서 결과 출력을 위한 String으로 바꿀 때(reduce) 기존String값에 맨 앞에 "0"이 들어있으면 무시하는 것으로 바꿔서 제출하니 통과가 되었다.

     

    최종 코드

    // 최종 코드
    import Foundation
    
    func solution(_ numbers:[Int]) -> String {
        return numbers.sorted {
            let s1 = String($0)
            let s2 = String($1)
            return s1 + s2 > s2 + s1
        }.reduce("") { 
            $0 != "0" ? $0 + String($1) : String($1)
        }
    }

     

     

    최종코드2 (6/19에 다시품)

    import Foundation
    
    func solution(_ numbers:[Int]) -> String {
        return numbers.sorted{
            return "\($0)\($1)" > "\($1)\($0)"
        }.reduce("") { $0 == "0" ? "\($1)":"\($0)\($1)" }
    }

    생각 정리

    Swift로는 삽입 정렬을 짜본적이 없어서 시험삼아 시간복잡도가 O(n^2) 인 삽입 정렬로 풀어보았는데 역시나 시간초과가 떴다. 도중에 Swift에서 내장 정렬은 어떤 알고리즘을 채택하고 있는지 찾아보니 Swift5기준 inplace-IntroSort 에서 Timsort 로 변경되는 등 계속해서 바뀌고 있다는 걸 확인했지만 처음 들어보는 알고리즘들이라 일단 이름만 기억하기로 했다..

    반응형

    댓글

Designed by Tistory.