Programmers

[프로그래머스] 올바른 괄호의 갯수 / Python

개발하는 사막여우 2021. 2. 6. 23:12
반응형

문제주소 :programmers.co.kr/learn/courses/30/lessons/12929

 

코딩테스트 연습 - 올바른 괄호의 갯수

올바른 괄호란 (())나 ()와 같이 올바르게 모두 닫힌 괄호를 의미합니다. )(나 ())() 와 같은 괄호는 올바르지 않은 괄호가 됩니다. 괄호 쌍의 개수 n이 주어질 때, n개의 괄호 쌍으로 만들 수 있는 모

programmers.co.kr


<문제 설명>

더보기

문제 설명

올바른 괄호란 (())나 ()와 같이 올바르게 모두 닫힌 괄호를 의미합니다. )(나 ())() 와 같은 괄호는 올바르지 않은 괄호가 됩니다. 괄호 쌍의 개수 n이 주어질 때, n개의 괄호 쌍으로 만들 수 있는 모든 가능한 괄호 문자열의 갯수를 반환하는 함수 solution을 완성해 주세요.

제한사항

  • 괄호 쌍의 개수 N : 1 ≤ n ≤ 14, N은 정수

입출력 예

nresult
2 2
3 5

입출력 예 설명

입출력 예 #1
2개의 괄호쌍으로 [ (()), ()() ]의 2가지를 만들 수 있습니다.
입출력 예 #2
3개의 괄호쌍으로 [ ((())), (()()), (())(), ()(()), ()()() ]의 5가지를 만들 수 있습니다.

 

<풀이법>

▒ 한줄 개념: memoization ▒ 

일종의 memoization을 이용하여 풀었습니다.

다만, 단순 반복문을 많이 사용하기도 하였습니다.

 

우선 규칙을 찾아야하는 것이 문제풀이의 시작입니다.

n = 1: '()' -> 1
n = 2 : '(())', '()()' -> 2
n = 3 : '((()))', '(()())', '()(())', '()()()', '(())()' -> 3
n = 4 : '(()()())', '(())()()', '(())(())', '((()))()', '(()())()', '()((()))', '()()(())', '()(()())', '(()(()))', '()(())()', '((()()))', '((())())', '()()()()', '(((())))' -> 14

이 모든 것을 하나의 배열 memo[]에 넣었다고 할 때, 다음과 같은 규칙을 찾을 수 있습니다.

 

  • memo[1]의 경우, 단순히 '()' 한 개 입니다.
  • memo[2]의 경우, 2가지로 나뉘어집니다.
    • '('와 ')' 사이에 memo[1]이 포함된 것 : '(())'
    • memo[1] + memo[1] : '()()'
  • memo[3]의 경우, 3가지로 나뉘어집니다.
    • '('와 ')' 사이에 memo[2]가 포함된 것 : '((()))', '(()())'
    • memo[1] + memo[2] : '()(())', '()()()'
    • memo[2] + memo[1] : '(())()', '()()()'
  • memo[4]의 경우, 4가지로 나뉘어집니다.
    • '('와 ')' 사이에 memo[3]이 포함된 것 : '(((())))', '((()()))', '((())())', '(()(()))', '(()()())'
    • memo[1] + memo[3] : '()((()))', '()(()())', '()(())()', '()()(())', '()()()()'
    • memo[3] + memo[1] : '((()))()', '(()())()', '(())()()', '()(())()', '()()()()'
    • memo[2] + memo[2] : '(())(())', '()()()()'

 

여기서 이제 규칙을 찾을 수 있습니다.

memo[n] = ['('와 ')' 사이에 memo[n-1]이 들어간 것들] + [i+j=n 인 모든 i,j에 대해 memo[i] * memo[j]]

 

따라서 반복문을 통해 이것을 단순히 구현하면 되겠습니다. 괄호쌍의 최대 갯수가 14라서, 시간이 크게 오래 걸리지 않습니다.

다만, 생각해야할 점은, memo[i] + memo[n-i]의 경우에서 중복을 문자열이 나오므로, set()함수를 통해 중복을 제거해주면 간단하게 해결할 수 있습니다.

 

<코드(Python)>

def solution(n):
    memo = [[],['()']]
    combis = [[]]
    for i in range(1, n + 1):
        kinds = []
        for j in range(1, i + 1):
            for k in range(1, i - j + 1):
                if j + k == i:
                    kinds.append((j,k))
        combis.append(kinds)
            
    for i in range(2, n+1):
        temp = []
        for l in memo[i-1]:
            temp.append('('+l+')')
        for j, k in combis[i]:
            for t1 in memo[j]:
                for t2 in memo[k]:
                    temp.append(t1+t2)              
        memo.append(list(set(temp)))
    print(memo)
        
    return len(memo[n])

 

 

더 많은 코드 보기(GitHub) : github.com/dwkim-97/CodingTest

 

 

반응형