이번 문제는 프로그래머스의 레벨 3 110 옮기기이다.
문제를 차근차근 한 번 읽어보도록 하자.
최대 1000000
개의 문자열이 주어진다.
이 때, 문자열의 길이는 최대 1000000
으로 정해지며,
주어진 문자열 길이의 합이 1000000
을 넘을 수 없다.
우리는 이제부터 문자열을 사전 순으로 가장 빠른 문자열로 고쳐야한다.
단, 부분 문자열 110
만을 옮겨 가장 빠른 문자열로 만들어라!
완전 탐색?
과연 완전 탐색으로 이 문제를 풀 수 있을까?
110
을 옮기는 모든 경우를 찾아보아야 하는 것인데,
직관적으로 보았을 때 불가능하다는 생각이 든다.
1000000
길이의 문자열 하나를 모두 완전탐색 하려면,
O(N^2)
혹은, 그 이상의 탐색이 필요하기 때문에 구체적으로 보아도 불가능하다.
Greedy?
그래서 그리디하게 풀 수 있는 방법이 있지 않을까 생각해보았다.
문득 어차피 110
보다 큰 수는 111
밖에 없다는 생각이 들었다.
그럼 앞에서 부터 111
을 찾고, 이후 나오는 110
과 교체해주면?
자연스럽게 사전 순으로 빨라지게 될 것이다.
또한 110
보다 뒤에 나오는 111
을 제외한 모든 문자열은?
당연히 110
보다 작은 문자열이 된다.
즉, 110
보다 뒤에 있는 경우엔 당연히 문자열 순서가 느려진다.
그럼 해당 문자열과 110
의 위치를 바꿔주어야 할 것이다.
여기까지는 생각을 할 수 있었다.
하지만 이것을 어떻게 구현할지가 문제이다.
111
을 찾아 바꾸는 것 까진 구현을 했으나, 그 이후가 문제였다.
110
보다 이후에 나오는 작은 수들과 바꾸는 과정을 구현하기 어려웠다.
또한 이 로직들에 대해서 제출을 했을 때 시간 초과가 발생함을 확인했다.
결국 다른 사람들의 풀이를 참고하게 되었다.
굉장히 놀라운 아이디어가 있었다.
110
보다 큰 숫자는 언급했다시피 111
뿐이다.
그래서, 만약 문자열에 0
이 없다면? 모든 110
은 앞에 붙는다.
그럼 만약 0
이 있다면? 이땐 가장 마지막 0
뒤에 110
이 붙는다.
어째서 이런 논리가 가능할까?
간단하게 생각해서, 0
이 큰 자리로 갈수록 숫자가 작아지기 때문이다.
만약 1110001
이라는 숫자가 있을 때, 가장 빠른 문자열을 만드려면?
110
을 100
뒤로 옮긴
1001101
`이 가장 빠른 문자열이 될 것이다.
가장 마지막 1
뒤로 옮긴 1001110
은 어떨까?
110
의 마지막 문자도 0
임을 우리는 간과해서는 안된다.
해당 0
이 마지막 1
보다 뒤로 간 탓에 문자열의 순서는 더 느려졌다.
따라서 우리가 해야할 일은 아래와 같다.
- 문자열에서 만들어지는
110
을 모두 제거한다. - 가장 마지막으로 등장하는
0
의 위치를 찾는다. - 해당 위치의 뒤로 제거한
110
들을 차례로 붙인다.
최종적으로 아래와 같이 구현되었다.
110
추출- 처음엔
find
함수를 이용해서 구현했지만, 시간초과가 발생했다. - 결국 직접
substr
를 이용해110
인 경우 즉시 지워주었다.
- 처음엔
for (int j = 0; j < s[i].size(); j++) {
result_str += s[i][j];
if (result_str.size() >= 3) {
if (result_str.substr(result_str.size() - 3, 3) == "110") {
zero_cnt++;
result_str.erase(result_str.size() - 3, result_str.size());
}
}
}
- 가장 마지막
0
찾기for
문 한 번으로 찾아낼 수 있다.- 찾지 못하는 경우는
1
밖에 없는 경우이다.
int zero_pos = -1;
for (int j = result_str.size() - 1; j >= 0; j--) {
if (result_str[j] == '0') {
zero_pos = j;
break;
}
}
string temp = "";
if (zero_pos == -1) {
// 문자열에 0이 없는 경우
while (zero_cnt--)
temp += "110";
temp += result_str;
answer.push_back(temp);
}
else {
for (int j = 0; j < result_str.size(); j++) {
if (j == zero_pos) {
temp += result_str[j];
while (zero_cnt--)
temp += "110";
}
else
temp += result_str[j];
}
answer.push_back(temp);
}