Algorithm Problem/Codility

Lesson 7. Stacks and Queues - Brackets

skyho 2024. 11. 24. 04:42

1. 문제

A string S consisting of N characters is considered to be properly nested if any of the following conditions is true:
  - S is empty;
  - S has the form "(U)" or "[U]" or "{U}" where U is a properly nested string;
  - S has the form "VW" where V and W are properly nested strings.

For example, the string "{[()()]}" is properly nested but "([)()]" is not.

Write a function:
  int solution(string &S);

that, given a string S consisting of N characters, returns 1 if S is properly nested and 0 otherwise.

For example, given S = "{[()()]}", the function should return 1 and given S = "([)()]", the function should return 0, as explained above.

Write an efficient algorithm for the following assumptions:
  - N is an integer within the range [0..200,000];
  - string S is made only of the following characters: '(', '{', '[', ']', '}' and/or ')'.

 

주어진 괄호 문자열(여러 종류의 괄호 포함)이 올바른 순서와 형태로 중첩되어 있는지 확인하는 문제

return 0: 잘못된 중첩 ( S = "([)()]" )

return 1: 올바른 중첩 ( S = "{[()()]}" )

 

2. 매개변수 제한

  • 문자열 길이: 0 ~ 200,000
  • 문자열을 구성하는 문자: '(', '{', '[', ']', '}', '/', ')'

 

3. 예제 분석

올바른 중첩 예제( S = "{[()()]}" )를 확인해보자.

index 문자 현재 문자 상태 비고
0 { {  
1 [ {[  
2 ( {[(  
3 ) {[ S[3]와 올바르게 중첩되는 문자로, S[3]와 함께 제거
4 ( {[(  
5 ) {[ S[4]와 올바르게 중첩되는 문자로, S[4]와 함께 제거
6 ] { S[1] 문자와 올바르게 중첩되는 문자로, 함께 제거
7 }   S[0]과 올바르게 중첩되는 문자로, 함께 제거

 

여기서 두 가지를 확인할 수 있다.

  • 현재 문자 상태를 stack으로 관리하면 된다.
  • 올바르게 중첩 된 문자는 최종적으로 빈 stack이 된다.

 

4. 주의할 점

빈 문자열이 입력되었을 때, 이는 올바른 중첩인가? 아닌가?

정답은 올바른 문자열이다.

왜냐하면 예제 분석에서 보았듯이, 올바르게 중첩된 문자는 최종적으로 빈 stack이 되기 때문이다.

즉, 빈 문자열이 입력되어서 빈 stack이 유지되든, 문자열을 다 처리 했는데 그 결과가 빈 stack 이든, 두 상태는 같은 상태이다. 

 

4. 코드 (C++)

#include <stack>

int solution(string &S) {

    if(S.empty()) return 1; // 빈 문자열

    stack<char> stack = {};
    char top = {};

    for(size_t i = 0; i < S.size(); i++)
    {
        // '/' 문자는 쌍을 이루지 않아도 된다
        if(S[i] == '/') continue;

        switch(S[i])
        {
            //괄호를 여는 문자는 무조건 삽입
            case '(':
            case '{':
            case '[':
                stack.push(S[i]);
                break;
            //괄호를 닫는 문자는 올바른 중첩인지 확인 필요
            case ')':
                top = stack.top();
                if(top != '(') return 0;
                stack.pop();
                break;
            case '}':
                top = stack.top();
                if(top != '{') return 0;
                stack.pop();
                break;
            case ']':
                top = stack.top();
                if(top != '[') return 0;
                stack.pop();
                break;
        }
    }

    if(stack.empty()) return 1; //최종적으로 stack이 비어야 올바른 중첩
    return 0;
}