프로그래머스 코딩테스트 정렬 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” |
풀이
원하는 값을 얻기위해선
- 배열의 두 수를 비교해서 각 숫자를 어떤 순서로 연결할지 결정해야 한다.
- 숫자의 순서를 정하는 방법은 두 수의 크기뿐 아니라 길이(자릿수)를 통해 비교해야 한다.
- 제한사항에서 numbers의 원소는 1,000 이하이므로 연산에 소요되는 시간은 크게 중요하지 않다.
처음에는 숫자들의 연결 순서를 정하기 위해 최적의 알고리즘을 생각하려했다.
먼저, 두 수의 자릿수를 비교한다. 만약 [403, 40]
으로 만들 수 있는 순서는 40340, 40403이다. 이때 40
을 결정하는 알고리즘은 다음과 같다.
- 각 원소의 자릿수를 계산 한 후, 둘 중 작은 자릿수의 값을 기억한다.
40
의 자릿수 ‘2’ - 두 수를 작은 자릿수(2) 자리만큼만 비교한다. [40]3 과 [40]
- 비교한 수가 같은경우 남은 자릿수(1)만큼 비교한다. 40[3] 과 [4]0
- 해당 자릿수의 값이 높은 원소가 우선순서로 결과 문자열에 연결된다.
하지만 채점을 했더니 몇가지 부분에서 실패를 해서 당황을 했는데, 사실 이 문제는 이렇게 복잡하게 접근할 필요가 없었다.. 두 원소로 만들 수 있는 문자열은 두가지 경우 뿐이므로 두가지 경우를 비교하여 정렬하면 되는 간단한 문제였다.
나는 built-in 함수인 sorted
를 응용해보았다. sorted
는 객체를 정렬할 때 매우 간편한데 이는 클래스에서 __lt__
, __gt__
등과 같이 비교연산을 하는 대소함수를 만들어주어 쉽게 구현이 가능하다.
코드(Python)
class Number:
def __init__(self, n):
self.number = n
def __lt__(self, other):
return int(str(self.number)+str(other.number)) > int(str(other.number)+str(self.number))
def solution(numbers):
answer = ''
number_list = []
for number in numbers:
number_list.append(Number(number))
number_list = sorted(number_list)
for a in number_list:
answer += str(a.number)
return answer if int(answer) > 0 else '0'
[추가] 코드(Java)
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Arrays;
import java.util.stream.Collectors;
class Solution {
public String solution(int[] numbers) {
Arrays.sort(numbers);
List<Integer> i_list = Arrays.asList(Arrays.stream(numbers).boxed().toArray(Integer[]::new));
Collections.sort(i_list, new Comparator<Integer>() {
public int compare(Integer i, Integer j) {
return (Integer.parseInt(i.toString() + j.toString()) < Integer.parseInt(j.toString() + i.toString()))
? 1
: -1;
}
});
return (i_list.stream().reduce((a, b) -> a + b).get() > 0)
? i_list.stream().map(Object::toString).collect(Collectors.joining())
: "0";
}
}
자바로도 알고리즘을 구현해보았는데, Comparator
를 이용한 정렬을 수행하였다.
if (condition) ? value1 : value2;
와 같은 구조로 코드를 간결하게 표현할 수 있었다.
댓글남기기