【刷题1】LeetCode 301. 删除无效的括号 java题解

好生气啊

题目

https://leetcode-cn.com/problems/remove-invalid-parentheses/
在这里插入图片描述

分析

一、找出左括号和右括号放错的数目。
1.我们从左边开始,一次处理一个括号的表达式。
2.假设我们遇到一个左括号,即 ( ,它可能会导致或可能不会导致一个无效的表达式,因为表达式的其余部分的某个地方可能有一个匹配的右括号。这里,我们只需增加计数器来跟踪左括号的出现次数。left++
3.如果我们遇到一个右括号,这有两种情况:
3.1 这个右括号没有匹配的左括号,该表达式是无效的。当 left == 0 时,即没有不匹配的左括号可用时,增加另一个计数器叫 right++ 来表示放错了位置的右括号。
3.2 有一些未匹配的左括号来匹配这个右括号。即,当 left > 0 时。在这种情况下,我们只需减小left 计数器,即 left - -
4.继续处理字符串,直到处理完所有括号。
5.最后,左括号和右括号的值分别表示不匹配 ( 和 ) 括号的数目。
二、回溯
@param ss 字符串对应的字符数组
@param sb 储存当前处理过且未去除字符的字符串
@param index 当前处理的字符位置
@param open 当前sb中储存的左括号数
@param close 当前sb中储存的右括号数
@param openRem 当前需要去除的左括号数
@param closeRem 当前需要去除的右括号数
1.已经处理完整个长度。如果左右多余扩号都已删除完毕,添加进结果集。
2.当前位置是左括号,删除,回溯下一位;当前位置是右括号,删除,回溯下一位。
3.不去掉当前位,将当前位加入当前字符串。
4.当前位置不为括号,则直接处理下一个字符
5.当前位置为左括号,增加左括号计数,处理下一个字符。
6.当前位置为右括号,且当前左括号计数大于右括号计数,则增加右括号计数,处理下一个字符
最后,从字符串去除当前位,以便回溯。

复杂度

时间复杂度:我们所执行的优化只是一种更好的修剪形式。在最坏的情况下,我们可以丢弃所有字符,因为所有字符都放错了位置。
在最坏的情况下,每个括号中仍然有两个选项,即是删除还是考虑它。考虑到表达式有 N 括号,时间复杂性将为 O(2^n)
空间复杂度:O(N)。 在到达基本情况之前,我们必须达到 N的最大递归深度。注意,我们不考虑存储有效表达式所需的空间。只计算中间过程空间。

代码

class Solution {
    private Set<String> set = new HashSet<>();
    public List<String> removeInvalidParentheses(String s) {
       
        if(s==null){
            ArrayList<String> l=new ArrayList<>();
            l.add("");
            return l;
        }
        char[] ss=s.toCharArray();
        int leftcount=0;
        int rightcount=0;
        for(int i=0;i<ss.length;i++){
            if(ss[i]=='(')
                leftcount++;
            else if(ss[i]==')'){
                if(leftcount>0)
                    leftcount--;
                else
                    rightcount++;
            }
        }
        dfs(ss,new StringBuilder(),0,0,0,leftcount,rightcount);
        return new ArrayList(set);
    }
    public void dfs(char[] ss,StringBuilder sb,int index,int open,int close,int openr,int closer){
        //1.已过最后一位
        if(index==ss.length){
            //1.1 已删除全部多余扩号
            if(openr==0&&closer==0){
                set.add(sb.toString());
                return;
            }
            //1.2 未删除全部多余扩号
            return;
        }
        //2.去掉当前位
        //2.1 当前位(
        if(ss[index]=='('&&openr>0){
            dfs(ss,sb,index+1,open,close,openr-1,closer);
        }
        //2.2 当前位)
        if(ss[index]==')'&&closer>0){
            dfs(ss,sb,index+1,open,close,openr,closer-1);
        }
        //3.不去掉当前位
        sb.append(ss[index]);
        //3.1 当前位(
        if(ss[index]=='('){
            dfs(ss,sb,index+1,open+1,close,openr,closer);
        }
        //3.2 当前位),且左括号计数大于右括号
        else if(ss[index]==')'&&open>close){
            dfs(ss,sb,index+1,open,close+1,openr,closer);
        }
        //3.2 当前位不是扩号
        else if(ss[index]!='('&&ss[index]!=')'){
            dfs(ss,sb,index+1,open,close,openr,closer);
        }
        //回溯
        sb.deleteCharAt(sb.length()-1);
    }
}

结果

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值