← 목록으로

프로그래머스 — 올바른 괄호

프로그래머스 — 올바른 괄호


0. 한눈에 보기

항목내용
플랫폼프로그래머스
문제올바른 괄호
핵심 아이디어스택으로 열린 괄호를 쌓고, 닫힌 괄호에서 짝을 맞춤
시간 복잡도O(n) — 문자열을 한 번만 순회
공간 복잡도O(n) — 최악의 경우 모두 '('

한 줄 요약: '('는 push, ')'는 pop. 중간에 스택이 비었거나 끝까지 스택이 남으면 false.


1. 문제

괄호가 바르게 짝지어졌다는 것은 '('로 열렸으면 반드시 ')'로 닫혀야 한다는 뜻이다.

  • 올바른 예: "()()", "(())()"
  • 올바르지 않은 예: ")()(", "(()("

'(' 또는 ')'로만 이루어진 문자열 s가 주어질 때, 올바른 괄호이면 true, 아니면 false를 반환한다.

제한사항

  • 문자열 s의 길이: 100,000 이하의 자연수
  • 문자열 s'(' 또는 ')'로만 구성

입출력 예

sanswer
"()()"true
"(())()"true
")()("false
"(()("false

2. 풀이 아이디어

괄호 짝 맞추기는 스택이 잘 맞는 대표 유형이다.

  1. '('를 만나면 스택에 push — “아직 닫히지 않은 열림”을 기록
  2. ')'를 만나면
    • 스택이 비어 있으면 → 짝이 될 열림이 없음 → 즉시 false
    • 비어 있지 않으면 → pop으로 짝을 하나 소모
  3. 문자열을 다 본 뒤
    • 스택에 남은 '('가 있으면 → 닫히지 않은 열림이 있음 → false
    • 스택이 비어 있으면 → true

길이 제한이 10만이라, 한 번 순회하는 O(n) 풀이면 충분하다.


3. 코드

function solution(s) {
    var answer = true;
    let stack = [];

    for (let i = 0; i < s.length; i++) {
        if (s[i] === '(') stack.push('(');
        else if (s[i] === ')') {
            if (stack.length === 0) return false;
            stack.pop();
        }
    }

    if (stack.length > 0) return false;

    return answer;
}

동작 흐름

단계코드의미
열림stack.push('(')짝을 기다리는 '(' 저장
닫힘 + 빈 스택return false')'가 먼저 나온 경우 (예: ")()(")
닫힘 + 스택 있음stack.pop()가장 최근 '('와 짝 맞춤
순회 후 스택 남음return false닫히지 않은 '(' 존재 (예: "(()(")
순회 후 스택 비움return true모든 괄호가 바르게 짝지어짐

예시 추적

"()()" → true

문자스택결과
([ ( ]
)[]pop
([ ( ]
)[]pop

끝에서 스택이 비어 있으므로 true.

")()(" → false

문자스택결과
)[]스택이 비어 있어 즉시 false

"(()(" → false

문자스택결과
([ ( ]
([ ( , ( ]
)[ ( ]pop
([ ( , ( ]

끝에서 스택에 2개가 남아 false.


4. 정리

  • 올바른 괄호 판별은 스택(또는 카운터) 로 풀 수 있다.
  • 이번 풀이는 스택에 '('를 쌓고 ')'에서 pop하는 방식이다.
  • 중간에 스택이 비었는데 ')'가 오거나, 끝까지 스택이 비지 않으면 올바르지 않다.
  • 문자열을 한 번만 보면 되므로 시간 복잡도 O(n), 제한(10만)에도 문제없다.

참고 — 카운터로 줄이기

스택에 실제 문자를 넣을 필요 없이, 열린 괄호 개수만 세어도 같은 판정이 가능하다.

function solution(s) {
    let count = 0;

    for (let i = 0; i < s.length; i++) {
        if (s[i] === '(') count++;
        else {
            if (count === 0) return false;
            count--;
        }
    }

    return count === 0;
}

의미는 동일하고, 공간은 O(1)로 줄어든다.