"(" and ")" characters only, and:
AB (A concatenated with B), where A and B are VPS's, or(A), where A is a VPS.We can similarly define the nesting depth depth(S) of any VPS S as follows:
depth("") = 0depth(A + B) = max(depth(A), depth(B)), where A and B are VPS'sdepth("(" + A + ")") = 1 + depth(A), where A is a VPS.For example, "", "()()", and "()(()())" are VPS's (with nesting depths 0, 1, and 2), and ")(" and "(()" are not VPS's.
Given a VPS seq, split it into two disjoint subsequences A and B, such that A and B are VPS's (and A.length + B.length = seq.length). The subsequences may not necessarily be contiguous.
For example, for the sequence 123456789, one possible split is:
A = {1, 3, 5, 7, 9},
B = {2, 4, 6, 8}.
This corresponds to the output [0, 1, 0, 1, 0, 1, 0, 1, 0] where 0 indicates membership in A and 1 indicates membership in B.
Now choose any such A and B such that max(depth(A), depth(B)) is the minimum possible value.
Return an answer array (of length seq.length) that encodes such a choice of A and B: answer[i] = 0 if seq[i] is part of A, else answer[i] = 1. Note that even though multiple answers may exist, you may return any of them.
Example 1:
Input: seq = "(()())" Output: [0,1,1,1,1,0]
Example 2:
Input: seq = "()(())()" Output: [0,0,0,1,1,0,1,1]
Constraints:
1 <= seq.size <= 10000문자열, 스택, Bracket Sequences
주어진 문자열 seq는 유효한 괄호 문자열(VPS)입니다. 이 문자열을 두 개의 부분 수열 A와 B로 분할해야 합니다.
조건은 다음과 같습니다.
A와 B 모두 유효한 괄호 문자열(VPS)이어야 합니다.A와 B는 seq의 문자를 겹치지 않게 나누어 가져야 합니다(순서 유지).max(depth(A), depth(B)) 값이 최소가 되도록 분할해야 합니다.출력은 seq의 각 문자가 A에 속하면 0, B에 속하면 1로 표시한 정수 배열입니다.
이 문제의 핵심 아이디어는 괄호의 깊이를 기준으로 홀짝(Parity)을 나누는 것입니다.
(는 깊이를 1 증가시키고, 닫는 괄호 )는 깊이를 1 감소시킵니다.D라고 할 때, 두 그룹으로 나누어 각각의 최대 깊이를 약 D/2로 줄이는 것이 목표입니다.0 또는 1)에 할당하면, 각 그룹 내에서는 깊이가 번갈아 가며 쌓이게 되어 최대 깊이가 절반 수준으로 줄어듭니다.cnt) 변수 하나만으로 홀짝 판별이 가능하므로 O(1) 추가 공간(출력 제외)으로 해결할 수 있습니다.cnt = 0
answer = []
cnt: 현재 괄호의 중첩 깊이(열린 괄호의 개수 - 닫힌 괄호의 개수)를 추적합니다.answer: 결과를 저장할 리스트입니다.for x in seq:
if x == "(":
# 여는 괄호 처리
...
else:
# 닫는 괄호 처리
...
문자열의 각 문자를 순차적으로 보며 여는 괄호인지 닫는 괄호인지에 따라 로직을 분기합니다.
( 처리 로직if x == "(":
if cnt % 2 == 1:
answer.append(1)
else:
answer.append(0)
cnt += 1
cnt)의 홀짝을 확인합니다.cnt % 2 == 1)면 그룹 1에, 짝수면 그룹 0에 할당합니다.cnt += 1).) 처리 로직else:
cnt -= 1
if cnt % 2 == 1:
answer.append(1)
else:
answer.append(0)
cnt)의 홀짝을 확인합니다.1, 짝수면 그룹 0에 할당합니다.시간 복잡도: O(N)
seq의 길이 N만큼 단 한 번 순회하며 각 문자에 대해 O(1) 연산(홀짝 판별, 리스트 추가)만 수행합니다.공간 복잡도: O(N)
answer 리스트의 크기가 N이므로 O(N)입니다.cnt, 루프 변수 등)는 상수 공간만 사용하므로 출력 공간을 제외하면 O(1)입니다.cnt)만으로 현재 깊이를 정확히 추적할 수 있습니다.class Solution:
def maxDepthAfterSplit(self, seq: str) -> list[int]:
cnt = 0
answer = []
for x in seq:
if x == "(":
if cnt % 2 == 1:
answer.append(1)
else:
answer.append(0)
cnt += 1
else:
cnt -= 1
if cnt % 2 == 1:
answer.append(1)
else:
answer.append(0)
return answer