LeetCode 1111 有效括号的嵌套深度 (Java版; Meidum)

welcome to my blog

LeetCode 1111. 有效括号的嵌套深度 (Java版; Meidum)

题目描述

有效括号字符串 仅由 "(" 和 ")" 构成,并符合下述几个条件之一:

空字符串
连接,可以记作 AB(A 与 B 连接),其中 A 和 B 都是有效括号字符串
嵌套,可以记作 (A),其中 A 是有效括号字符串
类似地,我们可以定义任意有效括号字符串 s 的 嵌套深度 depth(S):

s 为空时,depth("") = 0
s 为 A 与 B 连接时,depth(A + B) = max(depth(A), depth(B)),其中 A 和 B 都是有效括号字符串
s 为嵌套情况,depth("(" + A + ")") = 1 + depth(A),其中 A 是有效括号字符串
例如:"","()()",和 "()(()())" 都是有效括号字符串,嵌套深度分别为 0,1,2,而 ")(" 和 "(()" 都不是有效括号字符串。

 

给你一个有效括号字符串 seq,将其分成两个不相交的子序列 A 和 B,且 A 和 B 满足有效括号字符串的定义(注意:A.length + B.length = seq.length)。

现在,你需要从中选出 任意 一组有效括号字符串 A 和 B,使 max(depth(A), depth(B)) 的可能取值最小。

返回长度为 seq.length 答案数组 answer ,选择 A 还是 B 的编码规则是:如果 seq[i] 是 A 的一部分,
那么 answer[i] = 0。否则,answer[i] = 1。即便有多个满足要求的答案存在,你也只需返回 一个。

 

示例 1:

输入:seq = "(()())"
输出:[0,1,1,1,1,0]
示例 2:

输入:seq = "()(())()"
输出:[0,0,0,1,1,0,1,1]
 

提示:

1 <= text.size <= 10000

第一次做; 核心: 1)定义什么是同一层次的括号, 就是左括号和右括号相邻的两对括号, 或者说是右括号和左括号相邻的两对括号, 视觉上是这种样子)(; 2)同一层次的两组括号放在一起后的depth是1, 比如()(); 不同层次的两组括号放在一起后的depth是2, 比如(()) 3)根据索引, 以左括号为参考, 可以将层次分为奇数层和偶数层, 为了减少嵌套, 需要将偶数层的括号放在一起, 奇数层的括号放在一起; 4)不看题解就解不出来, 这咋整?

/*
同一层次的括号在一起
例子:
( ( ) ) ( )
0 1 2 3 4 5
0,3和4,5是同一层次的括号, 这样两部分的depth都是1, 作差的绝对值为0
但是如果0,3和1,2放在一组, 那么这部分的depth=2, 另一部分depth=1, 两部分depth作差的绝对值为1

应该将同一层次的括号放到一起
同一层次的左括号的下标的奇偶性相同, 以左括号为参照, 比如0,3和4,5, 属于偶数层的括号; 1,2属于奇数层的括号
同一层次的左括号的下标的奇偶性相同, 以左括号为参照, 比如0,3和4,5, 属于偶数层的括号; 1,2属于奇数层的括号
同一层次的左括号的下标的奇偶性相同, 以左括号为参照, 比如0,3和4,5, 属于偶数层的括号; 1,2属于奇数层的括号
其实将括号分成了两大类, 奇数层次的括号, 偶数层次的括号
将奇数层次的括号放在一起, 将偶数层次的括号放在一起
*/

class Solution {
    public int[] maxDepthAfterSplit(String seq) {
        int n = seq.length();
        int[] arr = new int[n];
        for(int i=0; i<n; i++){
            if(seq.charAt(i)=='('){
                //奇数层的左括号赋值为1, 偶数层的左括号赋值为0
                arr[i] = i & 1;
            }else{
                //奇数层的右括号的索引是偶数, 需要对该变量赋值为1; 偶数层的右括号的索引是奇数, 需要对改变量赋值为0
                arr[i] = (i-1) & 1;
            }
        }
        return arr;
    }
}

LeetCode优秀题解及优秀解释

解释一下第一种解法:首先,这是一个本质上讲所有括号对分成奇数层次和偶数层次的方法,奇数层次的放在一起,
偶数层次的放在一起。因为同一深度的左括号'('的下标奇偶性都是一样的,因为必然经过一个完成的结对过程,
如(())(),他们才能相遇,第0个’(“和第4个‘(’就时同一层次的,中间必然是一个偶数个数的结对,所以,
其下标奇偶性相等,奇数&1是1,偶数&1是0,就把左括号分成了两组了。然后,右括号和与其配对的左括号是相隔
奇数个数的,所以奇偶性相反,1-i&1讲奇偶取反,奇偶性相同,然后就可以和自己配对的左括号分到一组了。
public int[] maxDepthAfterSplit(String seq) {
    int n = seq.length(), res[] = new int[n];
    for (int i = 0; i < n; ++i)
        res[i] = seq.charAt(i) == '(' ? i & 1 : (1 - i & 1);
    return res;
}

力扣官方题解的方法一, 记录嵌套深度的方法也很好, 将嵌套深度为偶数的放在一起, 将嵌套深度为奇数的放在一起, 和上面的题解思路本质是一样的

方法一:用栈进行括号匹配
思路及算法

要求划分出使得最大嵌套深度最小的分组,我们首先得知道如何计算嵌套深度。我们可以通过栈实现括号匹配来计算:

维护一个栈 s,从左至右遍历括号字符串中的每一个字符:

如果当前字符是 (,就把 ( 压入栈中,此时这个 ( 的嵌套深度为栈的高度;

如果当前字符是 ),此时这个 ) 的嵌套深度为栈的高度,随后再从栈中弹出一个 (。

下面给出了括号序列 (()(())()) 在每一个字符处的嵌套深度:

括号序列   ( ( ) ( ( ) ) ( ) )
下标编号   0 1 2 3 4 5 6 7 8 9
嵌套深度   1 2 2 2 3 3 2 2 2 1

没有java版, 补充个

class Solution {
    public int[] maxDepthAfterSplit(String seq) {
        int n = seq.length();
        int[] arr = new int[n];
        int depth = 0;
        for(int i=0; i<n; i++){
            char ch = seq.charAt(i);
            if(ch=='('){
                depth++;
                //嵌套深度为奇数的放在一起
                arr[i] = depth & 1;
            }else{
                //嵌套深度为偶数的放在一起
                arr[i] = depth & 1;
                depth--;
            }
        }
        return arr;
    }
}

你可能感兴趣的:(AlibabaLeetCode)