LeetCode1249 移除无效的括号

题目

给你一个由 ‘(’、’)’ 和小写字母组成的字符串 s。

你需要从字符串中删除最少数目的 ‘(’ 或者 ‘)’ (可以删除任意位置的括号),使得剩下的「括号字符串」有效。

请返回任意一个合法字符串。

有效「括号字符串」应当符合以下 任意一条 要求:

  • 空字符串或只包含小写字母的字符串
  • 可以被写作 AB(A 连接 B)的字符串,其中 A 和 B 都是有效「括号字符串」
  • 可以被写作 (A) 的字符串,其中 A 是一个有效的「括号字符串」
    在这里插入图片描述

解题思路

本题可以使用栈实现,也可以用创建模拟栈顶指针实现

模拟栈顶指针思路:大体思路是创建栈顶指针top,左括号top+1,右括号top-1,正向遍历去除多余的')',再反向遍历去除多余的'('即可

栈方法思路:遍历字符串,遇到左括号,将其下标入栈,遇到右括号时,如果栈空,删除元素,否则弹栈,最后遍历栈,根据下标删除多于的左括号即可

代码

方法一:模拟指针

public String minRemoveToMakeValid(String s) {
        char[] c = s.toCharArray();
        StringBuffer s1 = new StringBuffer();
        //第一轮正向遍历:去掉多余的')'
        for (int i = 0, top=0; i < c.length; i++) {
            if(c[i] == '(') {
           		//如果遇到左括号,拼接进缓冲区,top+1;
                s1.append(c[i]);
                top++;
            } else if(c[i] == ')') {
            	//如果遇到右括号,如果当前没有左括号跟它匹配,那么不拼接金缓冲区,直接开始下次循环,否则拼接,top-1
                if(top == 0) continue;
                top--;
                s1.append(c[i]);
            }
            else{
            	//如果遇到字母,直接拼接
                s1.append(c[i]);
            }
        }
        //第二轮反向遍历,去掉多余的'('
        s = s1.toString();//缓冲区转为字符串
        c = s.toCharArray();//获取字符数组
        s1 = new StringBuffer();//开辟一个新的缓冲区
        for (int i = c.length-1, top = 0; i >= 0; i--) {
            if(c[i] == ')'){
            	//如果遇到右括号,直接拼接 top +1
                top++;
                s1.append(c[i]);
            }else if(c[i] == '('){
                if(top == 0) continue;
                top--;
                s1.append(c[i]);
            }else
                s1.append(c[i]);
        }
        //此时的缓冲区是逆序的,因为appen方法是追加至末尾,所以需要翻转缓冲区,再转换为字符串返回即可
        return s1.reverse().toString();
    }

方法二:栈

String[] str = s.split("");//转为字符串数组
        Stack<Integer> stack = new Stack<Integer>();//实例化栈
        //遍历数组
        for (int i = 0; i < str.length; i++) {
            //左括号
            if("(".equals(str[i])){
                //下标入栈
                stack.push(i);
            }
            //右括号
            if(")".equals(str[i])){
            	//如果栈非空,弹栈
                if(!stack.empty()) stack.pop();
                //否则删除该元素
                else{
                    str[i]=null;
                }
            }
        }
        //遍历栈删除多余的左括号
        for (Integer integer : stack) {
            str[integer] = null;
        }
        //将数组拼接为字符串
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < str.length; i++) {
            if(str[i] != null){
                sb.append(str[i]);
            }
        }
        return sb.toString();

总结

  1. JAVA中拼接字符串尽量使用StringBuffer,因为String类型本来就是"immutable(不可直接修改)的变量",使用"+"拼接会导致JVM内存泄露。
  2. StringBuffer中的append是追加到末尾,insert是追加到指定位置,虽然insert看着很方便,有时候不用翻转字符串,但是由于底层实现的原因,时间复杂度会大大高于append。
  3. 思路收获:所有数据结构内存的值,不仅仅是具体元素,也可以是它们的下标
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值