[JS 100] 53. 괄호 문자열

이춘구·2022년 8월 24일
0

js100

목록 보기
3/24

문제

괄호 문자열이란 괄호 기호인 { }, [ ], ( ) 와 같은 것을 말한다. 그중 괄호의 모양이 바르게 구성된 문자열을 바른 문자열, 그렇지 않은 문자열을 바르지 않은 문자열이라 부르도록 하자.

( ( ) ) 와 같은 문자열은 바른 문자열이지만 ( ) ( ) ) 와 같은 문자열은 바르지 않은 문자열이다.
(해당 문제에서는 소괄호만 판별하지만, 중괄호와 대괄호까지 판별해 보세요.)

입력으로 주어진 괄호 문자열이 바른 문자열인지 바르지 않은 문자열인지 "YES"와 "NO"로 구분된 문자열을 출력해보자.

해결방안

문제에서 정의한 바른 문자열이란 아래의 조건을 만족하는 것으로 보인다.

  • 여는 괄호, 닫는 괄호의 쌍으로 구성
  • 열려있는 괄호의 내부에서 새로운 괄호가 열리는 것은 가능 ex) [ { ( ) } ]
  • 하지만 다른 종류의 괄호가 닫히는 것은 불가능 ex) [ } ]

그러므로 특정 여는 괄호 뒤에 오는 닫는 괄호는 앞의 여는 괄호와 같은 종류여야 한다.

위 조건에 착안한 해결책은 이렇다.
입력받은 문자열을 배열로 만든 뒤 순회하며,
여는 괄호를 만나면, 해당 여는 괄호에 대응하는 닫는 괄호를 별도의 배열에 저장해놓고.
닫는 괄호를 만나면, 배열에 마지막으로 저장한 닫는 괄호와 일치하는지 검사한다.

const string = "[{()}]]";

function validateBrackets(string) {
  // 입력된 string을 배열로 만든다.
  const brackets = string.split("");
  // 여는 괄호에 대응하는 닫는 괄호를 저장할 배열을 선언한다.
  const expectedBrackets = [];

  // 빈배열이 들어왔다면 "FALSE" 반환하고 종료한다.
  if (brackets.length === 0) return "FALSE";
  
  // 입력받은 배열의 순회를 시작한다.
  for (const bracket of brackets) {
    // 각 여는 괄호마다 닫는 괄호가 있어야 하므로 여는 괄호에 대응되는 닫는 괄호를 배열에 추가한다.
    if (bracket === "(") {
      expectedBrackets.push(")");
    } else if (bracket === "{") {
      expectedBrackets.push("}");
    } else if (bracket === "[") {
      expectedBrackets.push("]");
      // 여는 괄호가 아닐 경우, 기대한 닫는 괄호 배열의 마지막 요소와 일치하는지 확인해서
    } else if (bracket === expectedBrackets.at(-1)) {
      // 일치한다면 해당 마지막 요소를 제거한다.
      expectedBrackets.pop();
    }
    // ( { [ 가 아니거나 일치하지 않는다면 'FALSE'를 반환한다.
    else return "FALSE";
  }

  // 순회를 무사히 마쳤다면 "TRUE"를 반환한다.
  return "TRUE";
}

const result = validateBrackets(string);
console.log("결과", result);

개선한 해결방안

여는 괄호와 닫는 괄호를 객체로 만들어 if문에서 괄호를 하나씩 비교하던 코드를 줄였다.

const string = "[{(}]";

// 여는 괄호에 대응되는 닫는 괄호를 객체로 만들어놓는다.
const pairBrackets = {
  "[": "]",
  "{": "}",
  "(": ")",
};

function validateBrackets(string) {
  // 입력된 string을 배열로 만든다.
  const brackets = string.split("");
  // 여는 괄호에 대응하는 닫는 괄호를 저장할 배열을 선언한다.
  const expectedBrackets = [];

  // 빈배열이 들어왔다면 "FALSE" 반환하고 종료한다.
  if (brackets.length === 0) return "FALSE";

  // 입력받은 배열의 순회를 시작한다.
  for (const bracket of brackets) {
    // 현재 순회하는 괄호의 짝을 객체에서 뽑아 pairBracket에 할당한다.
    // pairBracket의 값이 존재할 경우 현재 순회하는 괄호는 여는 괄호이다.
    const pairBracket = pairBrackets[bracket];

    // 여는 괄호일 경우, 각 여는 괄호마다 닫는 괄호가 있어야 하므로
    // 여는 괄호에 대응되는 닫는 괄호를 배열에 추가한다.
    if (pairBracket) {
      expectedBrackets.push(pairBracket);
      // 여는 괄호가 아닐 경우, 닫는 괄호 배열의 마지막 요소와 일치하는지 확인해서
    } else if (bracket === expectedBrackets.at(-1)) {
      // 일치한다면 제대로 된 닫는 괄호가 온 것이므로 해당 마지막 요소를 제거한다.
      expectedBrackets.pop();
    }
    // 일치하지 않는다면 'FALSE'를 반환한다.
    else return "FALSE";
  }

  // 순회를 무사히 마쳤다면 "TRUE"를 반환한다.
  return "TRUE";
}

const result = validateBrackets(string);
console.log("결과", result);
profile
프런트엔드 개발자

0개의 댓글