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시간 한 것 같다.