算法学习100天——17 分治思想
题目地址(241. 为运算表达式设计优先级)
https://leetcode-cn.com/problems/different-ways-to-add-parentheses/
题目描述
给你一个由数字和运算符组成的字符串 expression ,按不同优先级组合数字和运算符,计算并返回所有可能组合的结果。你可以 按任意顺序 返回答案。
示例 1:
输入:expression = "2-1-1"
输出:[0,2]
解释:
((2-1)-1) = 0
(2-(1-1)) = 2
示例 2:
输入:expression = "2*3-4*5"
输出:[-34,-14,-10,-10,10]
解释:
(2*(3-(4*5))) = -34
((2*3)-(4*5)) = -14
((2*(3-4))*5) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
提示:
1 <= expression.length <= 20
expression 由数字和算符 '+'、'-' 和 '*' 组成。
输入表达式中的所有整数值在范围 [0, 99]
思路
- 按照运算符号将表达式分开
- 分开后的表达式,分别计算两边的子表达式的值,结果存数组
- 遍历两边的数组,互相按照当前运算法计算,得到不同的结果
- 递归
Java Code
class Solution {
public List<Integer> diffWaysToCompute(String expression) {
// 分治法,将一个符号两边分开处理,计算出所有的子表达式的值存放进数组,然后交叉相乘
return divideAndCalculate(expression);
}
public List<Integer> divideAndCalculate(String expression){
List<Integer> res = new ArrayList<>();
// 递归出口
if(checkOnlyOneNum(expression)){
int num = 0;
for(char i : expression.toCharArray()){
num = num * 10 + (i - '0');
}
res.add(num);
return res;
}
// 根据符号,将符号两边的表达式分开,并获取所有子表达式的值,然后交叉计算
for(int i = 0; i < expression.length(); i++){
// 一直遍历,直到遇到算术符号
if(checkIsOperator(expression.charAt(i))){
List<Integer> left = divideAndCalculate(expression.substring(0, i));
List<Integer> right = divideAndCalculate(expression.substring(i + 1));
for(int l : left){
for(int r : right){
res.add(calculate(l, expression.charAt(i), r));
}
}
}
}
return res;
}
// 计算
private Integer calculate(int l, char charAt, int r) {
switch (charAt){
case '+' : return l + r;
case '-' : return l - r;
case '*' : return l * r;
default: return 0;
}
}
// 判断当前表达式是否只有一个数了
private boolean checkOnlyOneNum(String expression){
for(char c : expression.toCharArray()){
if(checkIsOperator(c)){
return false;
}
}
return true;
}
// 判断是不是操作符
private boolean checkIsOperator(char c){
return c == '+' || c == '-' || c == '*';
}
}