[JS] 110 옮기기
2022. 7. 21. 00:50
🔒 문제 (프로그래머스 월간 코드 챌린지 시즌 2)
0과 1로 이루어진 어떤 문자열 x에 대해서, 당신은 다음과 같은 행동을 통해 x를 최대한 사전 순으로 앞에 오도록 만들고자 합니다.
- x에 있는 "110"을 뽑아서, 임의의 위치에 다시 삽입합니다.
예를 들어, x = "11100" 일 때, 여기서 중앙에 있는 "110"을 뽑으면 x = "10" 이 됩니다. 뽑았던 "110"을 x의 맨 앞에 다시 삽입하면 x = "11010" 이 됩니다.
변형시킬 문자열 x가 여러 개 들어있는 문자열 배열 s가 주어졌을 때, 각 문자열에 대해서 위의 행동으로 변형해서 만들 수 있는 문자열 중 사전 순으로 가장 앞에 오는 문자열을 배열에 담아 return 하도록 solution 함수를 완성해주세요.
제한사항
- 1 ≤ s의 길이 ≤ 1,000,000
- 1 ≤ s의 각 원소 길이 ≤ 1,000,000
- 1 ≤ s의 모든 원소의 길이의 합 ≤ 1,000,000
🌊 입출력
s | result |
["1110","100111100","0111111010"] | ["1101","100110110","0110110111"] |
🔑 해결
🌌 알고리즘
110을 어떻게 배치해야 사전순으로 가장 앞설 수 있는지 그 방법을 찾는 것이 핵심인 문제.
0과 1을 이용한 3자리 문자열 조합을 살펴보면 110이 앞설 수 있는 조합은 111 뿐이다.
=> 원래 문자열보다 사전순으로 앞설 수 있는 경우는 연속된 1 앞에 110을 삽입하는 경우
따라서 할 일은 다음과 같다.
- 문자열을 변형하며 나오는 모든 110 탐색하여 제외시킨 문자열 얻기
- 얻은 문자열에서 1이 연속된 부분의 시작 지점 찾기
- 1이 연속된 부분의 시작에 탐색한 110 모두 붙여 답 찾기
이 때 s의 길이가 크기 때문에 1번 과정은 stack을 이용한다.
function solution(s) {
const answer = [];
for(const x of s) {
const stack = [];
let cnt = 0;
// 변형 과정 중 나오는 '110' 모두 제외한 문자를 가진 stack 생성
for(let i = 0; i < x.length; i++) {
const third = x[i];
if(stack.length > 1) {
const second = stack.pop();
const first = stack.pop();
if(first === '1' && second === '1' && third === '0') {
cnt++;
continue;
} else {
stack.push(first, second, third);
}
} else {
stack.push(third);
}
}
// '110' 구성 불가 시 그 문자열 자체가 답
if(!cnt) {
answer.push(x);
} else { // 1이 연속되는 지점의 시작 찾기
const arr = [];
while(stack.length) {
const last = stack.pop();
if(last === '0') {
stack.push(last);
break;
} else {
arr.push(last);
}
}
const str = '011'; // 스택에 반대로 넣은 것 고려
while(cnt) { // 1의 연속이 시작되는 지점에 '110' 삽입
arr.push(...str);
cnt--;
}
arr.reverse();
const result = stack.concat(arr).join('');
answer.push(result);
}
}
return answer;
}
'코딩테스트 (JS) > 스택 | 큐' 카테고리의 다른 글
[JS] 괄호 회전하기 (0) | 2022.11.16 |
---|---|
[JS] Backspace String Compare (0) | 2022.08.07 |
[JS] 큰 수 만들기 (0) | 2022.06.09 |