프로그래밍/코딩테스트

[프로그래머스] 가장 큰 수 / Swift

turu 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 로 변경되는 등 계속해서 바뀌고 있다는 걸 확인했지만 처음 들어보는 알고리즘들이라 일단 이름만 기억하기로 했다..

반응형