题目描述:
标签:递归 记忆化搜索 数学 字符串 动态规划
给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含
+
,-
以及*
。
代码:
思路分析:分治思想(其实画一棵树来表示递归就很容易理解了)
1、判断当前元素是不是运算符,是则将分为左右两个字符串进行递归,分别返回左字符串的结果leftList和右字符串的rightList,根据字符对两个list遍历进行符号运算。
2、如果当前字符串只有数字,一把来说是只有一个数字的时候,这个时候需要Integer.valueOf(expression)来添加该值。
3、这里有优化空间,因为某个字符串的值计算可能在之前已经计算过,所以可以用map存储每个字符串对应的结果,先检查map里面有没有,有的话就直接返回value,没有的话就进行上述的计算。
class Solution {
public List<Integer> diffWaysToCompute(String expression) {
if(expression == null || expression.length() <= 0){
return new ArrayList<Integer>();
}
List<Integer> ans = new ArrayList<>();
char[] ch = expression.toCharArray();
for(int i = 0;i < expression.length();i++){
char c = ch[i];
if(c == '+' || c == '-' || c == '*'){
List<Integer> leftList = diffWaysToCompute(expression.substring(0,i));
List<Integer> rightList = diffWaysToCompute(expression.substring(i+1));
for(int leftNum : leftList){
for(int rightNum : rightList){
if(c == '+'){
ans.add(leftNum + rightNum);
}else if(c == '-'){
ans.add(leftNum - rightNum);
}else{
ans.add(leftNum * rightNum);
}
}
}
}
}
if(ans.isEmpty()){
ans.add(Integer.valueOf(expression));
}
return ans;
}
}
《优化后》
class Solution {
Map<String, List<Integer>> map = new HashMap<>();
public List<Integer> diffWaysToCompute(String expression) {
if(expression == null || expression.length() <= 0){
return new ArrayList<Integer>();
}
if(map.containsKey(expression)){
return map.get(expression);
}
List<Integer> ans = new ArrayList<>();
char[] ch = expression.toCharArray();
for(int i = 0;i < expression.length();i++){
char c = ch[i];
if(c == '+' || c == '-' || c == '*'){
List<Integer> leftList = diffWaysToCompute(expression.substring(0,i));
List<Integer> rightList = diffWaysToCompute(expression.substring(i+1));
for(int leftNum : leftList){
for(int rightNum : rightList){
if(c == '+'){
ans.add(leftNum + rightNum);
}else if(c == '-'){
ans.add(leftNum - rightNum);
}else{
ans.add(leftNum * rightNum);
}
}
}
}
}
if(ans.isEmpty()){
ans.add(Integer.valueOf(expression));
}
map.put(expression,ans);
return ans;
}
}