[ JS 코딩테스트 LV 2] 괄호 회전하기

SeungJin·2022년 9월 28일
0

JS코딩테스트

목록 보기
63/111

문제 설명

다음 규칙을 지키는 문자열을 올바른 괄호 문자열이라고 정의합니다.

  • (), [], {} 는 모두 올바른 괄호 문자열입니다.
  • 만약 A가 올바른 괄호 문자열이라면, (A), [A], {A} 도 올바른 괄호 문자열입니다. 예를 들어, [] 가 올바른 괄호 문자열이므로, ([]) 도 올바른 괄호 문자열입니다.
  • 만약 A, B가 올바른 괄호 문자열이라면, AB 도 올바른 괄호 문자열입니다. 예를 들어, {} 와 ([]) 가 올바른 괄호 문자열이므로, {}([]) 도 올바른 괄호 문자열입니다.
  • 대괄호, 중괄호, 그리고 소괄호로 이루어진 문자열 s가 매개변수로 주어집니다. 이 s를 왼쪽으로 x (0 ≤ x < (s의 길이)) 칸만큼 회전시켰을 때 s가 올바른 괄호 문자열이 되게 하는 x의 개수를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • s의 길이는 1 이상 1,000 이하입니다.

입출력 예

sresult
"{}"3
"}]()[{"2
"[)(]"0
"}}}"0

입출력 예 설명

입출력 예 #1

  • 다음 표는 "{}" 를 회전시킨 모습을 나타낸 것입니다.
xs를 왼쪽으로 x칸만큼 회전올바른 괄호 문자열?
0"{}"O
1"](){}["X
2"(){}[]"O
3"){}[]("X
4"{}"O
5"}{"X
  • 올바른 괄호 문자열이 되는 x가 3개이므로, 3을 return 해야 합니다.

입출력 예 #2

  • 다음 표는 "}]()[{" 를 회전시킨 모습을 나타낸 것입니다.
xs를 왼쪽으로 x칸만큼 회전올바른 괄호 문자열?
0"}]()[{"X
1"]()[{}"X
2"()[{}]"O
3")[{}]("X
4"{}"O
5"{}]()["X

올바른 괄호 문자열이 되는 x가 2개이므로, 2를 return 해야 합니다.
입출력 예 #3

  • s를 어떻게 회전하더라도 올바른 괄호 문자열을 만들 수 없으므로, 0을 return 해야 합니다.

입출력 예 #4

  • s를 어떻게 회전하더라도 올바른 괄호 문자열을 만들 수 없으므로, 0을 return 해야 합니다.

풀이

const solution = (s) => {
    // 올바른 괄호를 카운터
    let answer = 0;
    // 문자열 s를 문자 배열로 변환
    s = s.split('');
    // 올바른 문자열은 괄호, 중괄호, 대괄호 한쌍씩 있어야 하므로 문자열의 길이가
    // 절대 홀수가 나올수 없음
    if (s.length === 1 || s.length % 2 !== 0) return 0;
    // 배열의 길이만큼 반복;
    for (let a = 0; a < s.length; a++) {
      // 배열 s의 0번째 원소가 '(', '{', '['로 시작하면 문자 배열을 체크해주는
      // 함수 실행후 실행 결과값을 더해줍니다.
      if (s[0] === '(' || s[0] === '{' || s[0] === '[') {
        answer += check(s);
      }
      // 조건문을 지나면 배열의 첫번째 요소를 뒤로 이동
      s.push(...s.splice(0, 1));
    }
    return answer;
  };



  // 호이스팅 되는 문자를 체크해 주는 함수
  function check(s) {
    // 배열의 요소를 순서대로 담을 배열 선언
    let arr = [];
    // 배열 s의 길이만큼 반복
    for (let b = 0; b <= s.length; b++) {
      // s[b]의 요소가 '(', '{', '['일 경우 arr에 Push
      switch (s[b]) {
        case '(':
          arr.push(s[b]);
          break;
        case '{':
          arr.push(s[b]);
          break;
        case '[':
          arr.push(s[b]);
          break;
        // s[b]의 요소가 ')', '}', ']'일 경우 현제 arr의 마지막 요소가
        // 해당 괄호의 여는 괄호 인지 확인
        case ')':
          // 마지막 요소가 해당 괄호의 여는 괄호가 아니라면 0을 리턴
          if (arr[arr.length - 1] !== '(') {
            return 0;
          }
          // 조건문을 통과하면 마지막 요소 삭제
          arr.pop();
          break;
        case '}':
          if (arr[arr.length - 1] !== '{') {
            return 0;
          }
          arr.pop();
          break;
        case ']':
          if (arr[arr.length - 1] !== '[') {
            return 0;
          }
          arr.pop();
          break;
      }
    }
    // 올바른 괄호일경우 반복문이 끝나는 시점에 arr의 길이는 0이 되어야 합니다.
    // arr의 길이가 0일경우 1 아니라면 0을 리턴
    return arr.length === 0 ? 1 : 0;
  }

추가설명

문제를 풀다가 계속 틀리던 부분이 괄호들의 개수에만 신경을 써서 순서를 놓쳐 한참을 해맸습니다( 테스트 케이스 14 ), s([{)}]일경우
제가작성한 풀이의 로직대로 순서대로 보면
1. arr.push(s[b]) -> arr[ '(' ]
2. arr.push(s[b]) -> arr[ '(', '[' ]
3. arr.push(s[b]) -> arr[ '(', '[', '{' ]
4. s[b]')' 이라면 arr의 마지막 요소가 '(' 되야 하지만
현제 arr -> arr[ '(', '[', '{' ] 이므로 스택(후입 선출)이 정상적으로 이뤄지지 않아서 올바른 문자열이 아닙니다.

profile
혼자 공부해 보고 적어두는 블로그입니다 문제 있다고 생각되시는 부분이 있으면 피드백이라도 남겨주시면 감사하겠습니다

0개의 댓글