leetcode 301-Remove Invalid Parentheses(hard)


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 ).

cases:

when come to the ith position:

1. if number of left paren is equal or larger than right paren, do nothing;

2. if number of left paren is less than right paren, invalid, we should delete one of the right paren on or on the left of ith position, each one can be deleted, but should notice those adjacent right paren, avoid duplicate cases.

after this round, we have removed the minimum number of invalid right paren, so what about left paren?

we can use the same way, only to reverse the string.

在产生valid parentheses的leetcode题中,就注意到了valid paren的条件是,在生成的过程中,右括号的个数不能大于左括号的个数。这道题也是基于这样的思路,当发现右括号的个数大于左括号时,肯定是invalid的,就需要删除掉一个右括号使得仍valid,至于删哪一个,答案是都可以,所以遍历一遍这一段,需要注意的是对于连续的右括号,单独删除哪一个得到的结果都是一样的,要避免duplicate。

这里有两个start的记录,一个istart,一个jstart,istart是记录检查是否invalid到了哪个位置,也就是说,istart之前都是检查过的,都是确保valid的;而jstart记录的是上一个删除掉了invalid paren的位置,当之后又发现invalid时,需要从上一个删除掉invalid paren的位置开始遍历,而不是从这一轮开始检查是否有valid的位置,可以说,istart是为了避免重复的检查中间这一段是否valid而设置的。

要注意return不要掉。

class Solution {
    public List<String> removeInvalidParentheses(String s) {
        List<String> list=new LinkedList<>();
        if(s==null) return list;
        removeInvalid(list, s, 0, 0, '(', ')');
        return list;
    }
    public void removeInvalid(List<String> list, String s, int istart, int jstart, char lc, char rc){
        int counter=0;
        for(int i=istart;i<s.length();i++){//对于已经遍历删除掉invalid paren的str来说,这一步会直接跳过
            if(s.charAt(i)==lc) counter++;
            else if(s.charAt(i)==rc) counter--;
            if(counter<0){
                for(int j=jstart;j<=i;j++){
                    if(s.charAt(j)==rc&&(j==jstart||s.charAt(j-1)!=rc)){
                        removeInvalid(list, s.substring(0,j)+s.substring(j+1),i,j,lc,rc);//在这个函数内recursive的删除了所有多余的char,并添加入list,str并不是在这一层加入list的,这个循环只是为了遍历所有可能的删除情况
                    }
                }
                return;//这个return很容易漏掉,// Stop here. The recursive calls handle the rest of the string.
            }
        }
        String str=new StringBuilder(s).reverse().toString();
        if(lc=='('){
            removeInvalid(list, str, 0,0,rc,lc);//反向过一遍删除掉多余的'('
        }
        else{
            list.add(str);
        }
    }
}

变形:

1. 返回最小的删除括号的个数,one pass,两个record

public int calculateMaxRemoval(String s) {
    int removel=0, remover=0;
    for(int i=0;i<s.length();i++){
        if(s.charAt(i)=='(') removel++;
        else if(s.charAt(i)==')'){
            if(removel!=0) removel--;
            else remover++;
        }
    }
    return removel+remover;
}

2. 返回valid parentheses(two pass)

思路和301原题一致,但只用返回一种valid的情况,简单一些。

    public String removeInvalidParentheses(String s) {
        if(s==null) return s;
        return removeInvalid(s,0,'(',')');
    }
    public String removeInvalid(String s, int start, char lc, char rc){
        int counter=0;
        for(int i=start;i<s.length();i++){
            if(s.charAt(i)==lc) counter++;
            else if(s.charAt(i)==rc) counter--;
            if(counter<0){
                return removeInvalid(s.substring(0,i)+s.substring(i+1),i,lc, rc);
            }
        }
        String str=new StringBuilder(s).reverse().toString();
        if(lc=='(') return removeInvalid(str,0,rc,lc);
        else return str;
    }

猜你喜欢

转载自www.cnblogs.com/yshi12/p/9716588.html