stack 사용하는 알고리즘 문제 풀이

백준 2504번

QEUSTION LINK

문제에서 주어진 괄호 각각의 형태에 따라 조건을 나누어 풀어야 하는 문제였습니다. stack 자료구조를 사용해서 풀어야 했는데, 처음에 풀 때에는 어떤 식으로 계산을 풀어나가야 할 지에 대해 의문이 들었습니다. 우선 다음과 같은 순서에 따라 문제를 풀고자 했습니다.

stack을 통해서 괄호가 일치하는 경우에 대해서만 처리해야한다는 사실은 인지했으나, 이미 계산이 된 숫자들을 어떤 식으로 담고, 처리를 진행해야할 지에 대해서는 어려움이 남았었습니다. 예를 들어, 아래와 같은 상황이 발생했습니다.

// '(()[][]' 여기까지 진행된 상태일 때, '])' 부분을 어떻게 처리할 지
const stack = ["(", 2, "[", 3, 3];
// 여기서 "]"가 나오면 3을 어떤 식으로 처리하고 넘어가야 할 지를 파악하지 못함

이 부분에서 어려움이 있었으나, 이후, stack에서 하나씩 pop을 할 때, 숫자가 나오면 해당 숫자들을 더하고, 다시 여는 괄호(”[”, “(”)가 나오면 해당 괄호에 관한 값을 곱해주면 된다는 것을 알 수 있었습니다.

let isResult = true;
// 괄호가 올바른 지에 대한 boolean 값

if (string === ")") {
  let insideValue = 0;
  // 현재 닫는 괄호의 내부에 있는 값들의 합
  let stop = false;
  let prevString = stack.pop();

  while (isResult && !stop) {
    // 여는 괄호가 나오면 기존에 더해두었던 값에 괄호에 해당하는 값을 곱해주고,
    // 값이 없는 경우(비어있는 경우) 2를 stack에 담아줌
    if (prevString === "(") {
      stack.push(insideValue * 2 || 2);
      stop = true;
      // 숫자가 나오면 해당 숫자를 기존에 있던 값에 더해주고, 다시 stack에서 pop
    } else if (typeof prevString === "number") {
      insideValue += prevString;
      prevString = stack.pop();
      // 숫자나 일치하는 여는 괄호가 아닐 시, 잘못된 괄호가 들어온 것이므로 결과가 틀렸음을 설정
    } else {
      isResult = false;
    }
  }
}

이러한 흐름으로 관련된 괄호들에 대한 모든 조건식을 만들어주면 아래와 같은 전체 코드가 나오게 됩니다.

const stringArray = input[0].split("");
// 입력값을 모두 쪼개둔 값
const stack = [];
let isResult = true;

stringArray.forEach((string) => {
  if (!isResult) return;
  if (string === "(") {
    stack.push(string);
  }
  if (string === ")") {
    let insideValue = 0;
    let stop = false;
    let prevString = stack.pop();

    while (isResult && !stop) {
      if (prevString === "(") {
        stack.push(insideValue * 2 || 2);
        stop = true;
      } else if (typeof prevString === "number") {
        insideValue += prevString;
        prevString = stack.pop();
      } else {
        isResult = false;
      }
    }
  }
  if (string === "[") {
    stack.push(string);
  }
  if (string === "]") {
    let insideValue = 0;
    let stop = false;
    let prevString = stack.pop();

    while (isResult && !stop) {
      if (prevString === "[") {
        stack.push(insideValue * 3 || 3);
        stop = true;
      } else if (typeof prevString === "number") {
        insideValue += prevString;
        prevString = stack.pop();
      } else {
        isResult = false;
      }
    }
  }
});

위 코드를 통해 stack 결과값을 가져올 때 올바른 괄호 배치가 이루어졌을 시에는 숫자만 담긴 배열이 나오게 됩니다. 하지만, 서로 일치하지 않는 괄호를 가진 경우에는 배열이 비어있거나, 괄호값이 남아있는 채로 stack 배열이 나오게 됩니다. 즉, 배열 내의 요소들이 숫자로만 이루어진 경우에만 해당 숫자값을 결과로 리턴하고 나머지는 0으로 리턴하면 됩니다.

const result = isResult ? stack.reduce((a, b) => a + b, 0) : 0;
console.log(typeof result === "number" ? result : 0);