[백준 | Javascript] 17413

박기영·2022년 9월 2일
0

백준

목록 보기
97/127

기초 알고리즘 1/2. 201 - 자료 구조 1(연습)
17413번. 단어 뒤집기 2

문제

17413번 문제 링크

solution

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(""));

참고 자료

참고 자료 1

profile
나를 믿는 사람들을, 실망시키지 않도록

0개의 댓글