括号系列问题总结

括号系列问题总结


32. Longest Valid Parentheses

Given a string containing just the characters ‘(’ and ‘)’, find the length of the longest valid (well-formed) parentheses substring.
Input: “(()”
Output: 2
Explanation: The longest valid parentheses substring is “()”

典型的dp问题。基于前面较短字符串的结果可以推导出当前的结果,但是这个过程略tricky。

现在设dp[i]是结束于i位置的LVP长度;那么我们需要基于a[i]来进行推导;
1.a[i] == ‘(’ ,很简单dp[i] = 0;
2.a[i] == ‘)’, 这种情况是这道题的难点。这里我们的目标就是找到上一个未匹配的左括号
(1)a[i-1] == ‘(’ ,这种情况相对简单,i和i-1必然是构成了一对括号,等于是在dp[i-2]的后面增加了长度为2的合法括号,则:

dp[i]=dp[i2]+2 d p [ i ] = d p [ i − 2 ] + 2
(2)a[i-1] == ‘)’ , 这里比较难考虑,我们举个例子: “( )(( ))” 对于这个字符串,考虑最后一个右括号的情况。这里最直接的想法就是试着去遍历来找,但是因为我们的数组已经记录了前面合法括号串的位置,也就是说我们可以使用这个信息来找到离当前位置最近的未匹配的字符x,如果x==’)’ 就意味着这里的右括号是冗余的,反之 x==’(‘那么这里的右括号就可以和x进行匹配,从而将 (x+1,i-1)这个字符串向两端各拓展一步得到了长度为 dp[i-1]+2的字符串; ERROR:自己编码的时候到这一步就直接作为dp[i]的值了,但分析发现这里其实和上面的情况类似,在找到一个合法子串(x,i)的时候,我们需要尝试将其拼接到dp[x-1]处,所以:
dp[i]=dp[idp[i1]1]+dp[i1]+2;idp[i1]1x) d p [ i ] = d p [ i − d p [ i − 1 ] − 1 ] + d p [ i − 1 ] + 2 ; ( i − d p [ i − 1 ] − 1 就 是 x )


22. Generate Parentheses

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

思路类似于backtrack , 跟踪左右括号的数量,注意只有所剩的右括号仍旧比所剩左括号多的时候,这时候我们已经用了更多的左括号,存在未匹配,所以可以加入右括号,否则的话会导致右括号变多;
由于我们第一次只能用左括号,所以直接在初始调用写好;

class Solution {
    List<String> res = new ArrayList<>();
    public List<String> generateParenthesis(int n) {
    //注意最开始的调用
        track(n-1,n,"(");
        return res;
    }

    public void track(int left,int right,String str){
        if(left==0 && right == 0){
            res.add(str);
            return;
        }
        if(right>left) track(left,right-1,str+")");
        if(left>0) track(left-1,right,str+"(");
    }
}

22. Generate Parentheses

Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators. The valid operators are +, - and *.
Example 1:
Input: “2-1-1”
Output: [0, 2]
Explanation:
((2-1)-1) = 0
(2-(1-1)) = 2

刚看到这道题会有点没有思路,括号题会基于常规思路往stack或者backtrack方面去考虑,但是会发现这道题很棘手,那么该用divide and conquer的思路:
对于每个运算符的两端如果我们分别加上括号,那么这个运算符将会是最后计算的,那么我们基于这种方法就将问题分成了两部分分别解决,对于前后两部分的结果根据符号做笛卡尔积就可以了。

class Solution {
    List<Integer> res = new ArrayList<>();
    char[] a;
    String str;
    Map<String,List<Integer>> m = new HashMap<>();
    public List<Integer> diffWaysToCompute(String input) {
        str = input;
        a = input.toCharArray();
        return divide(0,a.length-1);
    }

    public List<Integer> divide(int s,int e){
        String key = str.substring(s,e+1);
        if(m.containsKey(key)) return m.get(key);
        boolean num = true;
        List<Integer> res = new ArrayList<>();
        for(int i = s+1;i<e;i++){
            if(!Character.isDigit(a[i])){
                num = false;
                List<Integer> left = divide(s,i-1);
                List<Integer> right = divide(i+1,e);
                for(int x:left){
                    for(int y:right){
                        if(a[i] == '+') res.add(x+y);
                        else if(a[i] == '-') res.add(x-y);
                        else res.add(x*y);
                    }
                }
            }
        }
        if(num) res.add(Integer.valueOf(str.substring(s,e+1)));
        m.put(key,res);
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值