Hard-题目9:301. Remove Invalid Parentheses

题目原文:
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 ).

Examples:
“()())()” -> [“()()()”, “(())()”]
“(a)())()” -> [“(a)()()”, “(a())()”]
“)(” -> [“”]
题目大意:
给出一个括号和字母的字符串,其中有一些括号是失配的,求出所有去掉失配括号的解。
例如:
“()())()” -> [“()()()”, “(())()”]
(这个例子中多了一个右括号,但有两种去掉右括号的方式,故最后答案有2个解)
题目分析:
参考别人博客的解法,使用DFS求解。
首先定义“失配度”,代表字符串或其子串中失配括号的个数,博客中给出的解法大多使用了堆栈,其实不用,只用一个整形(相当于堆栈长度)维护即可,遇到左括号+1,遇到右括号如果长度不为0则减1,否则失配度+1,扫完字符串后加上这个长度(失配左括号数)。
然后从源字符串开始搜索,遍历字符串,如果当前字符串不是括号则跳过,否则计算去掉这个括号的失配度,如果比当前失配度小1,则继续向下搜索这个子串(说明继续寻找可以找到解),如果比当前失配度大1,则说明去掉这个括号不能得到解(因为继续搜索下去即使找到解也去掉了原来已经匹配的括号!),如果失配度=0则找到解。
这里需要用一个HashSet记录所有搜索过的字符串,如果一个字符串已经搜索过则不再搜索。这是个很重要的剪枝,否则会超时。因为对”((((((((((((((((((((((((((())”这个串,如果不做这个处理,第一层就会对每个去掉左括号的子串搜索一遍,而它们是一样的,可想而知有多少重复操作!
源码:(language:java)

public class Solution {
    HashSet<String> visited = new HashSet<String>();
    private int getMisses(String s) { // calculate the missing num of parentheses
        int parentheses = 0;
        int miss = 0;
        for(int i = 0;i<s.length();i++) {
            if(s.charAt(i) == '(')
                parentheses++;
            else if(s.charAt(i) == ')'){
                if(parentheses==0) 
                    miss++;
                else
                    parentheses--;
            }
        }
        miss+=parentheses;
        return miss;
    }
    private void dfs(List<String> list, String s, int miss) {
        if(miss == 0) 
            list.add(s);
        else {
            for(int i = 0;i<s.length();i++) {
                String nextStr = removeCharAt(s, i); 
                if(!visited.contains(nextStr)) {
                    visited.add(nextStr);
                    int nextMiss = getMisses(nextStr);
                    if(nextMiss<miss)
                        dfs(list, nextStr, nextMiss);
                }
            }
        }
    }
    private String removeCharAt(String s, int pos) {
          return s.substring(0, pos) + s.substring(pos + 1);
    }

    public List<String> removeInvalidParentheses(String s) {
        List<String> list = new ArrayList<String>();
        dfs(list,s,getMisses(s));
        return list;

    }
}

成绩:
23ms,beats 57.67%,众数3ms,13.37%
Cmershen的碎碎念:
3ms的办法也用到了递归,但不知道有没有回溯,在discuss https://leetcode.com/discuss/81478/easy-short-concise-and-fast-java-dfs-3-ms-solution中有介绍,但满篇E文让我懒得看,而博客中的中文分析大多与上述解法类似(我也是基于中文博客做的),还有一种基于bfs的,更慢且不易理解。

你可能感兴趣的:(Hard-题目9:301. Remove Invalid Parentheses)