Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
반응형
Archives
Today
Total
관리 메뉴

슈프림 블로그

[프로그래머스] 정렬 - 가장 큰 수 (Swift 풀이) 본문

코딩테스트

[프로그래머스] 정렬 - 가장 큰 수 (Swift 풀이)

_슈프림 2020. 9. 19. 21:15
728x90

# 실패 케이스 1

가장 먼저 생각했던 방식은 

1. 모든 Int형 배열로 들어온 입력값을 String형 배열로 변환한다.

2. 맨 앞자리를 비교하여 큰 수가 앞으로 가도록 정렬한다.

3. 정렬된 배열을 하나의 문자열로 변환한다. (joined 함수)

func solution(_ numbers:[Int]) -> String {
    var strings = numbers.map{String($0)}
    strings.sort{
        guard let first0 = $0.first, let first1 = $1.first else {
            return false
        }
        return first0 > first1
    }
    return strings.joined()
}

이 방식은 두번째 테스트 케이스를 통과하지 못했다.

3과 30과 34를 비교할 때, 세 숫자 모두 맨 앞자리가 동일하므로 정렬되지 않는 문제가 발생했다.

 

 

# 실패 케이스 2

두번째로 떠올린 방식은

1. 두 수를 맨 앞에서부터 비교하다가 큰 수가 먼저 나오는 수를 앞으로 가도록 정렬한다.

2. 짧은 길이의 숫자까지 다 비교했을 때 같으면, 길이가 긴 수 뒤에 나오는 숫자와, 짧은 길이의 맨 앞 숫자 중 큰 수를 앞으로 정렬한다.

func solution(_ numbers:[Int]) -> String {
    var strings = numbers.map{String($0)}
    
    strings.sort{
        // 비교할 수 있는 길이까지 비교
        let minLen = $0.count < $1.count ? $0.count : $1.count
        for i in 0..<minLen {
            let idx0 = $0.index($0.startIndex, offsetBy: i)
            let idx1 = $1.index($1.startIndex, offsetBy: i)
            
            if $0[idx0] < $1[idx1] { return false }
            else if $0[idx0] > $1[idx1] { return true }
        }
        
        // 비교할 수 있는 앞부분 숫자는 다 같고, 길이도 같을 때
        if $0.count == $1.count { return true }
        
        // 비교할 수 있는 앞부분 숫자는 다 같고, 길이가 다를 때
        let longer = $0.count > $1.count ? $0 : $1
        let nextIdx = longer.index(longer.startIndex, offsetBy: minLen)
        
        if longer[longer.startIndex] < longer[nextIdx] { return true }
        return false
    }
    
    return strings.joined()
}

이 경우는 테스트 케이스는 모두 통과했지만 채점을 해보니 엄청 많이 틀렸다... 뭘까.....

+ 생각해보니 22번째 줄(밑에서 6번째 줄)이 틀린 것 같다. return true의 의미는 $0과 $1중에 $0을 앞으로 정렬시키겠다는 뜻인데, 내가 짠 코드로만 보면 longer가 $0인지 $1인지 알 수 없어서 그런 것 같다. 당연한 논리인데 왜 생각을 못했지..

 

 

# 거의 다 온 케이스

마지막으로 생각한 방법은 진짜 간단했다.. 왜 진작 이 생각을 못했지?

문자열이기 때문에 + 연산자를 사용하면 숫자가 더해지는 것이 아니라 문자열이 이어붙여진다.

$0과 $1을 합친 문자열과 $1과 $0을 합친 문자열을 비교했을 때 더 큰 값이 되는 숫자를 앞으로 보내야 한다!!

얘들들어 1과 4가 있다면 14 와 41 중에 41이 크다. 따라서 4가 1보다 앞으로가도록 정렬해야 하는 것이다.

func solution(_ numbers:[Int]) -> String {
    var strings = numbers.map{String($0)}
    strings.sort{
        return $0+$1 > $1+$0
    }
    
    return strings.joined()
}

아니 근데.... 마지막.... 케이스 하나가 통과하지 못했다...

 

이유는 0이 들어오는 케이스 때문이었다!!!

입력으로 [0,0,0]이 들어오는 경우, 내 풀이 방식대로 하면 "000"이 리턴된다. 따라서 "0"이 리턴되도록 처리해 주는 코드가 필요했다.

나는 String값을 Int값으로 바꿔주고, 그 값을 다시 String 으로 변환하여 반환하는 방식으로 구현해서 해결하였다. (6째 줄 주목)

이번 문제는 단 5줄로 해결하였다!

func solution(_ numbers:[Int]) -> String {
    var strings = numbers.map{String($0)}
    strings.sort{ $0+$1 > $1+$0 }
    
    let answer = strings.joined()
    if let num = Int(answer) { return String(num) }
    return answer
}
반응형
Comments