-
[프로그래머스] 42746_가장 큰 수(c++)Problem Solving/PROGRAMMERS 2019. 11. 25. 18:44
문제 설명
0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수를 알아내 주세요.
예를 들어, 주어진 정수가 [6, 10, 2]라면 [6102, 6210, 1062, 1026, 2610, 2106]를 만들 수 있고, 이중 가장 큰 수는 6210입니다.
0 또는 양의 정수가 담긴 배열 numbers가 매개변수로 주어질 때, 순서를 재배치하여 만들 수 있는 가장 큰 수를 문자열로 바꾸어 return 하도록 solution 함수를 작성해주세요.
제한 사항
- numbers의 길이는 1 이상 100,000 이하입니다.
- numbers의 원소는 0 이상 1,000 이하입니다.
- 정답이 너무 클 수 있으니 문자열로 바꾸어 return 합니다.
입출력 예
numbersreturn
[6, 10, 2] 6210 [3, 30, 34, 5, 9] 9534330
#C++ 첫 접근
-만들 수 있는 모든 경우의 수를 다 구하고 가장 큰 숫자를 결과 값으로 반환하면 된다고 생각함.
-그래서 C++에서 가장 애정하는 next_permutation을 이용하여 구현했음.
#include <string> #include <vector> #include <algorithm> using namespace std; string solution(vector<int> numbers) { //가장 큰 수 - fail vector<string> tmp; sort(numbers.begin(), numbers.end()); do{ string s = ""; for(int i = 0; i < numbers.size(); i++){ s += to_string(numbers[i]); } tmp.push_back(s); } while(next_permutation(numbers.begin(), numbers.end())); sort(tmp.begin(), tmp.end()); return tmp[tmp.size() - 1]; }
실행 결과
테스트 케이스는 모두 통과하나 제출한 후 시간 초과가 남.
제한 사항을 제대로 보지 못했다는 것을 느꼈음. C++ STL에서 제공하는 next_permutation의 경우 시간복잡도가 O(N)으로 n제한인 100,000에 do - while 안 for 문까지 고려하면 1초 안에 연산이 불가능함. 즉 터지는 코드임.
#C++ 두 번째 접근
-모든 경우의 수를 다 계산하면 시간복잡도에서 터지는 결과가 나오기 때문에 다른 방식으로 접근함.
-두 개의 숫자를 정렬할 때 기준을 두기로 결정함.
-두 숫자의 string 합을 비교하여 우위에 둘 숫자를 결정하게 했음.
입출력 예제 [3, 30, 34, 5, 9] 을 예로 들어보자.
3과 30 중에 우위를 정하는 방법은 3 + 30 => 330과 30 + 3 => 303을 비교하는 것임.
이렇게 할 경우 앞자리가 3으로 동일하더라도 어떤 것이 우위에 올지 결정할 수 있음.
Step 1. [3, 30, 34, 5, 9]
3 + 30 => 330, 30 + 3 => 303 ------> 330 > 303 따라서, 3이 우위가 됨. -> 3, 30, 34, 5, 9
30 + 34 => 3034, 34 + 30 => 3430 -----> 3034 < 3430 따라서, 34가 우위가 됨. -> 3, 34, 30, 5, 9
30 + 5 => 305, 5 + 30 => 530 -----> 305 < 530 따라서, 5가 우위가 됨. -> 3, 34, 5, 30, 9
30 + 9 => 309, 9 + 30 => 930 -----> 309 < 930 따라서, 9가 우위가 됨. -> 3, 34, 5, 9, 30
Step 2. [3, 34, 5, 9, 30]
3 + 34 => 334, 34 + 3 => 343 -----> 334 < 343 따라서, 34가 우위가 됨. -> 34, 3, 5, 9, 30
3 + 5 => 35, 5 + 9 => 59 -----> 35 < 59 따라서, 5가 우위가 됨. -> 34, 5, 3, 9, 30
3 + 9 => 39, 9 + 3 => 93 -----> 39 < 93 따라서, 9가 우위가 됨. -> 34, 5, 9, 3, 30
3 + 30 => 330, 30 + 3 => 303 -----> 330 > 303 따라서, 3이 우위가 됨. -> 34, 5, 9, 3, 30
Step 3. [34, 5, 9, 3, 30]
34 + 5 => 345, 5 + 34 => 534 -----> 345 > 534 따라서, 5가 우위가 됨. -> 5, 34, 9, 3, 30
34 + 9 => 349, 9 + 34 => 934 -----> 349 < 934 따라서, 9가 우위가 됨. -> 5, 9, 34, 3, 30
34 + 3 => 343, 3 + 34 => 334 -----> 343 > 334 따라서, 34가 우위가 됨. -> 5, 9, 34, 3, 30
3 + 30 => 330, 30 + 3 => 303 -----> 330 > 303 따라서, 3이 우위가 됨. -> 34, 5, 9, 3, 30
이렇게 계속해서 구하다보면 [9, 5, 34, 3, 30]의 결과가 나옴.
-cmp라는 함수를 만들어주고 위의 과정처럼 풀 수 있도록 조건을 주었음. a + b > b + a인 경우에 true가 되도록 메소드를 작성하였음.
-sort(tmp의 처음부터, tmp의 마지막까지, cmp에 정의한 것을 기준으로) 정렬을 수행했음.
-하나 주의해야할 점은, 결과로 이어붙인 answer의 0번째 인덱스가 0인 경우 가장 큰 수가 0이라는 뜻이므로 0을 리턴해줘야 함!!
#include <iostream> #include <string> #include <vector> #include <algorithm> using namespace std; bool cmp(const string &a, const string &b) { //string으로 비교 수행 return a + b > b + a; } string solution(vector<int> numbers) { //가장 큰 수 - success string answer = ""; vector<string> tmp; for (int i = 0; i < numbers.size(); i++) tmp.push_back(to_string(numbers[i])); sort(tmp.begin(), tmp.end(), cmp); //cmp 함수 기준으로 정렬 수행 for (int i = 0; i < tmp.size(); i++) answer += tmp[i]; if (answer[0] == '0') return "0"; //answer[0]가 0이면 가장 큰 수가 0이라는 뜻이므로 0리턴 return answer; }
실행 결과
모든 테스트 케이스가 정상적으로 실행됨.
'Problem Solving > PROGRAMMERS' 카테고리의 다른 글
[프로그래머스] 12905_가장 큰 정사각형 찾기(c++) (0) 2019.11.12 [프로그래머스] 43162_네트워크(java, c++) (0) 2019.11.12 [프로그래머스] 42883_큰 수 만들기(c++) (2) 2019.11.12 [프로그래머스] 42587_프린터(java, c++) (0) 2019.11.10