[알고리즘] 가장 큰 수

백상휘·2020년 8월 31일
0

알고리즘

목록 보기
1/4

해당 문제는 프로그래머스(https://programmers.co.kr/learn/courses/30/lessons/42746)에 출제된 문제를 채점한 결과를 토대로 작성하였습니다.

Int 배열이 주어진 상태에서 모든 조합을 따져보았을 때 가장 큰 수가 나오는 조합을 String 형태로 반환하라는 문제다.

필요한 작업 : 정렬, 데이터 형 변환(Int -> String)

명제 :
'맨 앞의 수가 크다면 무조건 우선순위를 갖는게 맞다'
'맨 앞의 수가 똑같은 두 수라면 서로 앞 뒤를 다르게 조합해 본 다음 우선순위를 정한다'

생각해낸 아이디어 :
1. 배열의 모든 정수를 1의 자리로 만들고, 애초에 10 이상이라면 맨 앞의 수 나머지는 모두 소수점으로 밀어버린다.
예) 1 => 1.0, 20 => 2.0, 9 => 9.0, 3210 => 3.21
'맨 앞의 수가 크다면 무조건 우선순위를 갖는게 맞다' 라는 명제를 충족해야 하기 때문이다.
2. 배열을 비교할 때 두 정수를 String으로 바꾸면 서로 붙였을 때 어떤 쪽이 더 큰지 알 수 있다.
예) 6, 10 => 610/106 이므로 6이 앞에 나와야 함,
324, 305 => 305324/324305 이므로 324가 앞에 나와야 함

우선 배열의 크기만큼 작업시간은 길어질 수 밖에 없을 거라고 생각했다. 배열을 정렬하는 일은 필수이기 때문이다.

func solution(_ numbers:[Int]) -> String {
    var numbers = numbers
    
    numbers.sort {
    // 숫자를 문자열로 바꿀 때 10의 '문자열 길이 - 1'제곱을 나누면 일의 자리로 만들 수 있음
        let lhs = Double($0) / pow(10.0, Double(String($0).count-1))
        let rhs = Double($1) / pow(10.0, Double(String($1).count-1))
        
        // 일의 자리만 비교해서 크고 적음이 가려진다면 바로 반환
        if lhs.rounded(.down) > rhs.rounded(.down) {
            return true
        } else if lhs.rounded(.down) < rhs.rounded(.down) {
            return false
        } else {
            // 두 정수를 앞 뒤로 붙이기 위해 각각을 문자열로 바꾼 뒤 정수로 바꿔준다.
            if Int(String($0) + String($1))! > Int(String($1) + String($0))! {
                return true
            } else {
                return false
            }
        }
    }
    
    // 배열 앞에 0이 있으면 제외한다.
    while numbers.first ?? 1 == 0 && numbers.count > 1 {
        numbers.removeFirst()
    }
    // 위의 코드는 다음과 같이 변형 가능하다.
    // if numbers.reduce(0, {$0+$1}) == 0 { return "0" }

    return numbers.reduce("", {$0+String($1)})
}

이렇게 간단한 것을 3~4시간 한 것 같다.

profile
plug-compatible programming unit

0개의 댓글