LeetCode-java 1021.删除最外层括号(简单)

题1021:类型:栈

  • 题目
     有效括号字符串为空 ("")、"(" + A + ")" 或 A + B,其中 A 和 B 都是有效的括号字符串,+ 代表字符串的连接。例如,"","()","(())()" 和 "(()(()))" 都是有效的括号字符串。
     如果有效字符串 S 非空,且不存在将其拆分为 S = A+B 的方法,我们称其为原语,其中 A 和 B 都是非空有效括号字符串。
     给出一个非空有效字符串 S,考虑将其进行原语化分解,使得:S = P_1 + P_2 + ... + P_k,其中 P_i 是有效括号字符串原语。对 S 进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 S 。
    示例 :
    输入:"(()())(())"
    输出:"()()()"
    解释:
    输入字符串为 "(()())(())",原语化分解得到 "(()())" + "(())",
    删除每个部分中的最外层括号后得到 "()()" + "()" = "()()()"。
    提示:
    S.length <= 10000
    S[i] 为 "(" 或 ")"
    S 是一个有效括号字符串
  • 方法一、直接用栈实现
    1、新建栈,临时存储字符并且代替计数器;
    2、遍历字符串:左括号入栈,右括号出栈;
    3、若栈为空,找到了一个完整的原语,截取并拼接。
class Solution {
    public String removeOuterParentheses(String S) {
        //新建栈,临时存储字符,代替计数器
        Stack s = new Stack<>();
        StringBuilder sb = new StringBuilder();//结果字符串
        int sign = 0; // 原语左标识,i是右标识
        //遍历字符串,满足原语条件,直接定位剔除最外层括号后的字符串
        for(int i = 0;i < S.length(); ++i){
            char ch =  S.charAt(i);
            if(ch == '('){
                s.push(ch);
            }else if(ch == ')') { // 此处判断条件可删除
                s.pop();
            }
            // 判断栈是否为空,若为空,找到了一个完整的原语  
            if(s.isEmpty()){
                // 删除原语子串最外层(),并拼接其余子串
                sb.append(S.substring(sign+1 , i)); // [ ),左开右闭
                sign = i + 1;  // 初始化原语左标识初始位置
            }
        }
        return sb.toString();
    }
}
  • 方法二、用数组代替栈
     1、直接用数组取代栈,但是逻辑上还是栈;
     2、将原字符串转换为字符数组进行遍历,节省了循环中多次调用charAt()方法的时间;
     3、读取到左括号: 若该左括号之前有数据,当前为原语 ; 同理,读取到右括号,匹配后数组内仍不为0,当前为原语,最后拼接。

注意:第三步的思想中,判断出的原语已经包含了剔除最外层括号的步骤。

class Solution {
    public String removeOuterParentheses(String S) {
        //用数组代替栈,逻辑上还是栈
        int len = S.length();
        int index = -1; // '栈'顶索引
        char[] stack = new char[len];
        //结果字符串
        StringBuilder sb = new StringBuilder();
        // 原字符串转化为字符数组
        char[] s = S.toCharArray();
        //  遍历字符数组
        for(int i = 0;i < len; ++i){
            char ch =  s[i];
            if(ch == '('){
                // 判断在前
                if(index > -1){
                    sb.append(ch); // 拼接子串
                }
                stack[++index] = ch;
            }else if(ch == ')') {
                stack[index--] = '\u0000';
                // 判断在右括号匹配后
                if(index > -1){
                    sb.append(ch);
                }
            }
        }
        return sb.toString();
    }
}
  • 方法三、计数器代替栈
     1、直接用计数器代替,左括号+1,右括号-1,依然采用栈的逻辑进行判断;
     2、将原字符串转换为字符数组进行遍历,节省了循环中多次调用charAt()方法的时间;
     3、读取到左括号: 若该左括号之前有数据(计数器大于0),当前为原语 ,然后计数器加1; 同理,读取到右括号,匹配后数组内仍不为0(计数器减1后仍大于0),当前为原语,最后拼接。

注意:第三步的思想中,判断出的原语已经包含了剔除最外层括号的步骤。

class Solution {
    public String removeOuterParentheses(String S) {
        //用数组代替栈,逻辑上还是栈
        int len = S.length();
        // 计数器,左括号+1,右括号-1
        int count = 0;
        //结果字符串
        StringBuilder sb = new StringBuilder();
        // 原字符串转化为字符数组
        char[] s = S.toCharArray();

        for(int i = 0;i < len; ++i){
            char ch =  s[i];
            if(ch == '('){
                // 根据计数判断左右括号是否为原语
                if(count > 0){ // 此前有数据
                    sb.append(ch);
                }
                count++;
            }else if(ch == ')') {
                count--;
                if(count > 0){ // 右括号之后不为0,自减后仍有数据
                    sb.append(ch);
                }
            }
        }
        return sb.toString();
    }
}

你可能感兴趣的:(LeetCode-java 1021.删除最外层括号(简单))