기초 알고리즘 1/2. 201 - 자료 구조 1(연습)
17413번. 단어 뒤집기 2
const fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().trim().split("");
let stack = [];
let word = "";
let isTag = false;
let ans = "";
for (let str of input) {
if (str === "<") {
isTag = true;
// "<" 기호 앞에 문자가 있다면 뒤집어서 이어붙여준다.
ans += word.split("").reverse().join("") + str;
// 다음 문자를 받아서 처리하기 위해 word를 초기화한다.
word = "";
} else if (str === ">") {
isTag = false;
// 태그가 끝났으므로 word에 넣어둔 문자열들과 함께 ans에 넣어준다.
ans += word + str;
// 다음 문자를 받아서 처리하기 위해 word를 초기화한다.
word = "";
} else if (str === " ") {
// 공백이 있다면, 태그 내 공백인지, 문자 사이의 공백인지 판단해야한다.
// 만약, 태그 내 공백이라면 그대로 word와 함께 공백 문자를 ans에 추가한다.
// 문자 사이의 공백이면 구분해줘야하므로, word에 들어있는 문자를 뒤집고, 공백 문자와 함께 ans에 넣어준다.
ans += (!isTag ? word.split("").reverse().join("") : word) + " ";
// 다음 문자를 받아서 처리하기 위해 word를 초기화한다.
word = "";
} else {
// 위 조건에 해당하지않으면 word 배열에 넣어준다.
// 이는 태그 내부든지 일반 문자든지 구분하지 않는다.
word += str;
}
}
// 만약 ">" 기호로 태그가 닫히는 것으로 끝나는게 아니라,
// 문자로 끝나는 경우에는 word에 넣어진 상태로 for문이 종료된다.
// 양 끝에는 공백이 없기 때문에 분기처리가 안되고 else문만 실행되고 종료되기 때문이다.
// 따라서 출력 전에 word를 뒤집어서 바꿔줄 필요가 있다.
ans += word.split("").reverse().join("");
console.log(ans);
결국 메모리 초과를 해결하지 못해서 다른 분의 풀이를 참고했다.
접근 방법은 맞았지만, 풀어내는 방법이 너무나도 달랐다.
메모리 초과가 발생하는 원인을 알 수 없다는게 아쉽지만, while문의 과도한 사용이 문제가 아니었나싶다.
이번에는 주석을 보면서 따라가는 것도 이해가 잘 되기 때문에, 예시 설명은 생략!
const fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().trim().split("");
let stack = [];
let ans = [];
let count = 0;
// input과 ans의 길이가 같아지면 모든 문자열을 처리한 것이므로, while문 종료
while(ans.length !== input.length){
let str = input[count];
// 처음과 끝은 공백이 아니기 때문에 이 부분은 문자에 대해서만 작동함
if(str === " "){
// stack에 있는 문자열을 뒤집고
stack.reverse();
// ans와 합쳐준다.
ans.concat(stack);
// stack에 있는 문자열을 전부 저장했으므로 다시 비워준다.
stack = [];
// stack에 있는 문자를 넣어줬으면, 그 다음 공백을 ans에 넣는다.
ans.push(str);
// 공백 다음 문자를 확인하기 위해 미리 count를 증가시키고
count++;
// 다시 while문 처음으로 돌아간다.
continue;
}
// "<" 문자를 만나면 태그이므로 그대로 출력해야함
if(str === "<"){
// 다른 작업을 하기 전에 stack을 먼저 확인
if(stack.length > 0){
// stack에 값이 존재하면 원소들을 뒤집어서 ans에 넣어준다.
stack.reverse()
}
// 따라서, 그대로 ans에 push
ans.push(str);
// ">" 문자를 만나기 전까지 계속 반복해야하므로 count 증가
count++;
// ">" 문자를 만나면 false가 되므로 while문이 종료될 것
while(str !== ">"){
let tag = input[count];
// 태그에 해당하는 문자를 ans에 push
ans.push(tag);
// 다음 문자를 확인하기 위해 count 증가
count++;
}
// while문이 종료되면 count번 인덱스를 가지는 문자는 ">"이므로, 얘까지 ans에 넣어줘야함
ans.push(input[count]);
// ">" 다음 문자열을 확인하기 위해 count를 미리 증가시키고 while문을 종료해야함.
count++;
// ">" 문자까지 넣어줬으면 continue를 통해 while문 처음으로 다시 돌아가서 진행.
continue;
} else {
// 태그가 아닌 문자는 뒤집어 줘야하므로 stack에 넣어준다.
stack.push(str);
// 다음 문자를 확인하기 위해 count 증가
count++;
// 공백을 만나기 전까지 문자들은 하나의 문자이므로 while문으로 stack에 저장
while(str !== " "){
let word = input[count];
stack.push(word);
// 다음 문자를 확인하기 위해 count 증가
count++;
}
// 공백까지 stack에 넣어버리면 공백을 포함해서 문자열이 뒤집히므로 여기서는 공백을 처리하면 안된다.
// 공백 문자열을 처리하기 위해 while문 처음으로 간다.
continue;
}
}
console.log(ans.join(""));