leetcode 301. Remove Invalid Parentheses(去除无效括号)

本文介绍了一种算法,用于从输入字符串中移除最小数量的无效括号,使其成为有效字符串。通过统计需要删除的括号数量,并使用深度优先搜索(DFS)遍历所有可能的组合,最终得到所有可能的有效输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results.

Note: The input string may contain letters other than the parentheses ( and ).

Example 1:

Input: “()())()”
Output: ["()()()", “(())()”]
Example 2:

Input: “(a)())()”
Output: ["(a)()()", “(a())()”]
Example 3:

Input: “)(”
Output: [""]

给出一个字符串,移除最小数量的括号,使得输入有效(即左括号和右括号匹配),要求输出所有有效的输出。

思路:
首先要判断括号是否匹配,即输入是否有效。
以前判断括号有效常用到Stack,这里模拟Stack,右括号出现时,左括号出栈,没有左括号时说明无效。即字符串没有结束时,右括号的数量要少于左括号,字符串结束时,左右括号数量相等。

    public boolean isValid(String s) {
        int count = 0;
        
        //i < length(s): left count >= right count
        //i = length(s): left count = right count
        for(int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                count ++;
            } else if (s.charAt(i) == ')') {
                count --;
            }
            
            if (count < 0) {
                return false;
            }
        }
        
        return (count == 0);
    }

因为要删除最小数量的括号,所以要统计出左括号要删掉多少个,右括号要删掉多少个。
要删除的左括号的数量可以用上面的思路,出现一个左括号+1,出现一个右括号-1,左括号的数量为0时如果出现右括号,说明需要删除的右括号+1。

        for(int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                left ++;
            } else if (s.charAt(i) == ')') {
                if (left == 0) {
                    right ++;
                } else {
                    left --;
                }
            }           
        }

知道了需要删除多少个左括号,多少个右括号,接下来就是遍历输入的字符串,删除掉这么多括号即可,删除掉之后要检测字符串是否有效,有效的话添加到输出的list中。
但是比如几个括号连续时,如 " ( ( ( ) ", 前3个左括号删除掉哪一个结果都是一样的,所以当出现连续相同括号时,只删除掉第一个。 删除掉一个后,以当前index为起始点,遍历剩下部分的substring,同时前面统计的要删除的左括号数量-1,进入下一轮递归,也就是DFS。

注意:
java中string不能直接操作,要用StringBuilder, 如果直接把StringBuilder做DFS参数,StringBuilder是Object型,DFS返回以后会是修改过的字符串,而不是传入DFS前的字符串,因此需要新建一个StringBuilder保存DFS处理前的字符串。
这里给DFS传入string型

    public List<String> removeInvalidParentheses(String s) {
        int left = 0;
        int right = 0;
        List<String> result = new ArrayList<>();
        
        for(int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                left ++;
            } else if (s.charAt(i) == ')') {
                if (left == 0) {
                    right ++;
                } else {
                    left --;
                }
            }
            
        }
        
        //StringBuilder sb = new StringBuilder(s);
        dfs(s, 0, left, right, result);
        return result;
    }
    
    public void dfs(String s, int start, int left, int right, List<String> result) {
        if (left == 0 && right == 0) {
            if(isValid(s)) {
                result.add(s);
            }
            return;
        }
        
        for(int i = start; i < s.length(); i++) {
        //有重复的括号出现时,只删除第一个,其余跳过
            if (i > start && s.charAt(i) == s.charAt(i - 1)) {
                continue;
            }
            
            if (s.charAt(i) == '(' || s.charAt(i) == ')') {
                //string不能修改,建立StringBuilder
                StringBuilder sb = new StringBuilder(s);
                sb.deleteCharAt(i);
                
                //delete ')' first
                if (right > 0 && s.charAt(i) == ')') {                   
                    dfs(sb.toString(), i, left, right - 1, result);
                }
                if (left > 0 && s.charAt(i) == '(') {
                    dfs(sb.toString(), i, left - 1, right, result);
                }
            }
        }
    }
    
    public boolean isValid(String s) {
        int count = 0;
        
        //i < length(s): left count >= right count
        //i = length(s): left count = right count
        for(int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                count ++;
            } else if (s.charAt(i) == ')') {
                count --;
            }
            
            if (count < 0) {
                return false;
            }
        }
        
        return (count == 0);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值