문제
https://www.acmicpc.net/problem/1406
정답 코드
const fs = require("fs");
const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const input = fs.readFileSync(filePath).toString().trim().split("\n");
function solution(input) {
const initialString = input[0];
const commands = input.slice(2);
// 스택 두개 초기화
const leftStack = initialString.split("");
const rightStack = [];
for (const command of commands) {
const [cmd, char] = command.split(" ");
switch (cmd) {
case "L":
if (leftStack.length > 0) {
rightStack.push(leftStack.pop());
}
break;
case "D":
if (rightStack.length > 0) {
leftStack.push(rightStack.pop());
}
break;
case "B":
if (leftStack.length > 0) {
leftStack.pop();
}
break;
case "P":
leftStack.push(char);
break;
}
}
return leftStack.concat(rightStack.reverse()).join("");
}
console.log(solution(input));
두 개의 스택을 사용했다. 스택은 요소 삽입 삭제의 시간 복잡도가 O(1) 로 매우 빠르다. 따라서 해당 방법으로 시간제한을 통과하도록 구현할 수 있었다.
- leftStack : 커서 왼쪽에 있는 문자 저장
- rightStack : 커서 오른쪽에 있는 문자 저장
- rightStack.reverse() : 오른쪽 스택의 문자의 순서를 뒤집어서 순서 조정
시간복잡도
- 각 스택의 push/pop : O(1)
- reverse() : O(N)
- 총 시간 복잡도는 O(M + N)
풀이
첫 번째 시도 풀이
const fs = require("fs");
const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const input = fs.readFileSync(filePath).toString().split("\n");
function solution(input) {
const strArr = input[0].split("");
let cursor = strArr.length; // 커서 초기 위치
for (let i = 2; i < input.length; i++) {
const command = input[i].split("");
switch (command[0]) {
case "L":
if (cursor > 0) {
cursor--;
}
break;
case "D":
if (cursor < strArr.length) {
cursor++;
}
break;
case "B": // 왼쪽 삭제
if (cursor > 0) {
strArr.splice(cursor - 1, 1);
cursor--;
}
break;
case "P":
strArr.splice(cursor, 0, command[2]);
cursor++;
break;
}
}
return strArr.join("");
}
console.log(solution(input));
처음에 구현한 코드가 시간 초과가 발생했다. 시간 초과의 원인을 분석하고 시간 제한을 만족시키기위한 해결 방법을 찾아보았다.
시간 초과 원인
splice() 사용한 것에 문제가 있다.
- 배열의 특정 위치에 문자를 추가/삭제 하기 위해서 splice() 메서드를 사용했다.
- splice() 는 배열의 크기 N 에 비례한 시간복잡도 O(N) 을 가진다. 따라서 배열의 크기가 클수록 실행 시간이 급격히 늘어난다.
문제 조건은 다음과 같았다.
- 최대 명령어 개수 : M = 500,000
- 최대 문자열 길이 : N = 100,000
- 최악의 경우 O(M x N) 의 시간복잡도를 가진다.
시간 복잡도 계산
- O(M x N) = 500,000 x 100,000 = 50,000,000,000 (500 억 번의 연산)
- 문제의 시간 제한은 0.3 이다. 보통 1초에 약 1억번 연산이 가능한것을 보았을 때, 해당 코드는 500억 번의 연산을 요구하므로 최대 500초가 걸려서 시간 초과가 발생한다.
시간 제한 내 문제를 해결하려면
- 0.3초 : 100,000,000 x 0.3 = 30,000,000 이므로 최대 30,000,000 연산을 넘지 않아야한다.
- 두 개의 스택을 사용하여 요소 추가/삭제를 O(1) 시간복잡도로 처리할 수 있도록 해야한다.
- 커서를 중심으로 문자열을 왼쪽 스택과 오른쪽 스택으로 나누어 처리하면, 커서 이동 및 문자 추가/삭제 작업을 모두 빠르게 수행할 수 있다.
'코딩문제풀기' 카테고리의 다른 글
[백준] 14681 | 사분면 고르기 | 자바스크립트 (0) | 2024.12.30 |
---|---|
[백준] 1158 | 요세푸스 문제 | Javascript (1) | 2024.12.24 |
[백준/9093] 단어 뒤집기 (0) | 2024.12.02 |
[백준/9012] 괄호 (0) | 2024.10.16 |
[프로그래머스/12916] 문자열 내 p와 y의 개수 (2) | 2024.07.22 |