[JS] 괄호 회전하기

2022. 7. 21. 17:57알고리즘/programmers

큐 문제입니다.

큐 안에 커스텀 함수 하나만 만들어주면 인생 편해지더라구요.

같이 풀어보시죠!


문제 요약

대괄호, 중괄호, 그리고 소괄호로 이루어진 문자열 s가 매개변수로 주어집니다. 이 s를 왼쪽으로 x (0 ≤ x < (s의 길이)) 칸만큼 회전시켰을 때 s가 올바른 괄호 문자열이 되게 하는 x의 개수를 return 하도록 solution 함수를 완성해주세요.

s length
"[](){}" 3
"}]()[{" 2
"[)(]" 0
"}}}" 0

 

접근법

위에 설명한 대로 큐를 이용해볼 겁니다.

일단 s 요소 그대로 큐에 다 넣어줍니다.

반복문 안에서 일단 다 올바른 괄호인지 체크해주고, dequeue한 값을 다시 enqueue 해주면 되겠군요.

 

올바른 괄호인지 체크해주는 부분이 핵심로직입니다.

 

정답 코드

class Queue {
    constructor() {
        this.queue = [];
        this.front = 0;
        this.rear = 0;
    }
    
    enqueue(val) {
        this.queue[this.rear++] = val;
    }
    
    dequeue() {
        const val = this.queue[this.front];
        delete this.queue[this.front];
        this.front++
        return val;
    }
    
    isAllRight() {
        const current = this.queue;
        let cursor = this.front;
        const stack = [];
        while (cursor < this.rear) {
            let val = "";
            switch(current[cursor]) {
                case "(":
                    stack.push("(");
                    break;
                case ")":
                    val = stack.pop();
                    if (val !== "(") return false;
                    break;
                case "[":
                    stack.push("[");
                    break;
                case "]":
                    val = stack.pop();
                    if (val !== "[") return false;
                    break; 
                case "{":
                    stack.push("{");
                    break;
                case "}":
                    val = stack.pop();
                    if (val !== "{") return false;
                    break;
                default:
                    return false;
            }
            cursor++;
        }
        if (stack.length === 0) return true;
        return false;
    }
}

function solution(s) {
    if (s.length === 1) return 0;
    const queue = new Queue();
    const n = s.length;
    for (const letter of s) queue.enqueue(letter);
    
    let i = 0;
    let count = 0;
    while (i < n) {
        if (queue.isAllRight()) {
            count++;
        }
        const val = queue.dequeue();
        queue.enqueue(val);
        i++;
    }
    
    return count;
}

 

함수 isAllRight에 대해서

이게 모든 코드의 절반이네요. 별건 없는데 그냥 스위치문이 하나 들어가면서 길어졌네요.

따로 함수로 뺄 수 있을 것 같은데 클래스 안에서 또 다른 함수 만들어 줘도 되나...? 싶기도 하네요.

여기는 private public 개념이 없으니 뭔가 그냥 생성자로 만들고 접근 할 수 있을 것 같기도 하고

(찾아봤더니 함수나 생성자앞에 #을 붙이면 private하게 만들 수 있군요. 음.... 그렇군...
관심 있으신 분들은 https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Classes/Private_class_fields 한번 보고 오세요!)

 

크게 어렵진 않아요. 그냥 평범한 stack입니다.

isAllRight() {
    const current = this.queue;
    let cursor = this.front;
    const stack = [];
    while (cursor < this.rear) {
        let val = "";
        switch(current[cursor]) {
            case "(":
                stack.push("(");
                break;
            case ")":
                val = stack.pop();
                if (val !== "(") return false;
                break;
            case "[":
                stack.push("[");
                break;
            case "]":
                val = stack.pop();
                if (val !== "[") return false;
                break; 
            case "{":
                stack.push("{");
                break;
            case "}":
                val = stack.pop();
                if (val !== "{") return false;
                break;
            default:
                return false;
        }
        cursor++;
    }
    if (stack.length === 0) return true;
    return false;
}

처음에는 그냥 숫자 변수로 지정한다음 +1, -1을 해주면서 체크를 해줬었는데

테스트 14번이 에러가 나더라구요.

예를 들어 s = "({)}" 이런 식이면 올바르진 않지만 숫자로 체크해주면 알아낼 수 없습니다. 그냥 스택을 쓰는게 맘 편하겠더라구요.

 

그럼 이만!