정렬 문제
https://programmers.co.kr/learn/courses/30/lessons/42746
[문제 풀이]
주어진 정수를 잘 조합하여 가장 큰 수를 만드는 문제입니다.
단순하게 생각하자면 모든 조합을 전부 구하고 가장 큰 수를 확인할 수도 있습니다.
numbers의 길이가 n, numbers원소의 길이가 l이라 하면 시간 복잡도는 $O(n! \, n^2 \, l)$의 시간 복잡도를 갖습니다.
(모든 조합을 구하는 시간 복잡도 $O(n!)$, 길이가 $nl$인 문자열들 중 최댓값을 찾는 시간 복잡도 $O(n \, nl)$
n의 최대가 10만이므로 말도 안 되는 풀이입니다.
모든 원소에 대한 조합을 전부 구하고 비교하는 과정이 매우 비효율적입니다.
하지만 2개의 원소만 뽑아서 구해본다면,
예를 들어 numbers가 [21, 394]라고 가정하면 21394와 39421만 비교하면 됩니다.
2개의 원소만 뽑아서 보는게 무슨 소용이 있을까요?
정렬을 떠올린다면 소용이 있습니다.
정렬은 두 개의 원소를 비교한 후 서로의 위치를 바꾸는 과정을 반복하여 원소들을 특정 기준에 맞춰 나열합니다.
즉 정렬 기준을 두 원소 A, B를 받아 A + B와 B + A를 비교하는 방식으로 바꾼다면 numbers 배열을 나열했을 때 가장 큰 수 혹은 가장 작은 수를 만들 수 있게 됩니다.
정렬의 시간 복잡도는 $O(nlogn)$이고 매 정렬마다 A + B, B + A를 비교하는 시간 복잡도는 $O(1)$이므로 위 풀이의 총 시간 복잡도는 $O(nlogn)$입니다.
n이 10만이므로 충분히 시간 제한을 통과할 수 있습니다.
하지만 위의 과정으로 풀어도 틀리는 케이스가 존재합니다.
numbers가 [0, 0]이라면 답은 "0"이지만 numbers를 나열하면 "00"입니다.
즉, numbers를 나열했을 때, "00 ... 0"의 꼴이라면 "0"을 출력시키면 됩니다.
더 간단한 방법으로는 정렬을 마친 numbers[0]가 0이라면 "0"을 출력시키면 됩니다.
A + B와 B + A를 비교하는 방법으로 가장 큰 수를 만들면 0은 가장 우선 순위가 낮게 정렬됩니다.
그럼에도 불구하고 가장 앞자리인 numbers[0]이 0이라면 적어도 "0 ..."의 형태를 띠고 있음을 나타냅니다.
그러므로 "0"으로 출력해도 문제가 없습니다.
[소스 코드]
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
using namespace std;
bool cmp(int a, int b) {
string s1, s2;
stringstream ss;
ss << a << b;
s1 = ss.str();
ss.str("");
ss << b << a;
s2 = ss.str();
return s1 > s2;
}
string solution(vector<int> numbers) {
sort(numbers.begin(), numbers.end(), cmp);
stringstream ss;
for (int n : numbers) {
ss << n;
}
if (numbers[0] == 0) return 0;
else return ss.str();
}
'Algorithm > Programmers' 카테고리의 다른 글
[프로그래머스 코딩테스트 고득점 Kit - 완전탐색] 모의고사 (2) | 2021.07.05 |
---|---|
[프로그래머스 코딩테스트 고득점 Kit - 정렬] H-Index (0) | 2021.06.28 |
[프로그래머스 코딩테스트 고득점 Kit - 정렬] K번째수 (0) | 2021.03.17 |
[프로그래머스 코딩테스트 고득점 Kit - 힙(Heap)] 이중우선순위큐 (0) | 2021.03.09 |
[프로그래머스 코딩테스트 고득점 Kit - 힙(Heap)] 디스크 컨트롤러 (0) | 2021.03.08 |