1. 程式人生 > >leetcode 301-Remove Invalid Parentheses(hard)

leetcode 301-Remove Invalid Parentheses(hard)

-- posit The stop this 所有 結果 直接 letters


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;
    }

leetcode 301-Remove Invalid Parentheses(hard)