括号系列问题总结
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的合法括号,则:
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;
}
}