分治
分治相关的题目如下:
序号 | 题目 | 难度 |
---|---|---|
1 | 241. 为运算表达式设计优先级 | 中等 |
应用
1. Leetcode 241. 为运算表达式设计优先级
1.1. 题目
给你一个由数字和运算符组成的字符串 expression ,按不同优先级组合数字和运算符,计算并返回所有可能组合的结果。你可以 按任意顺序 返回答案。
生成的测试用例满足其对应输出值符合 32 位整数范围,不同结果的数量不超过 \(10^4\) 。
示例 1:
输入: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.2. 分析
我们利用分治的思想,以表达式中的运算符作为分割符,将原始的运算符分割成子表达式和运算符。
我们定义一个递归函数:List<Integer> calculate(String expression)
,用于计算一个表达式的所有可能得计算结果。
通过递归的方式,直到将每一个子表达式分割成一个数字为止,然后,再根据对应的运算符,使用后序遍历,依次合并操作数的计算结果,最终即可得到运算的结果。
这里,由于需要枚举所有的可能优先级组合,因此,我们回溯的时候,需要枚举表达式中的每一个运算符的位置,以它作为起点开始分割表达式。
例如,我们以用例 expression = "2*3-4*5"
为例,来介绍分治的过程:
-
第一种情况:以第一个运算符 \(expression[1]\) 分割原始的表达式,得到三个子表达式即:
2
、*
、3-4*5
,分解的过程如下: -
第二种情况:以第二个运算符 \(expression[3]\) 分割原始的表达式,得到三个子表达式即:
2*3
、-
、4*5
,分解的过程如下: -
第三种情况:以第三个运算符 \(expression[5]\) 分割原始的表达式,得到三个子表达式即:
2*3-4
、*
、5
,分解的过程如下:
1.3. 代码实现
class Solution {
private static final Set<Character> OPERATORS = new HashSet<>();
public List<Integer> diffWaysToCompute(String expression) {
OPERATORS.add('+');
OPERATORS.add('-');
OPERATORS.add('*');
return calculate(expression);
}
private List<Integer> calculate(String expression) {
// 计算每条路径上,每个节点返回的结果
List<Integer> result = new ArrayList<>();
// 枚举表达式中的运算符
for (int i = 0; i < expression.length(); i++) {
// 如果当前字符不是运算符,则跳过
if (!OPERATORS.contains(expression.charAt(i))) {
continue;
}
// 分治:将原始的表达式按照运算符分割成两个子表达式,并记录子表达式的值
List<Integer> prevNums = calculate(expression.substring(0, i));
List<Integer> postNums = calculate(expression.substring(i + 1));
// 后序遍历:枚举当前运算符,与前后两个子表达式的计算结果的组合
for (Integer prevNum : prevNums) {
for (Integer postNum : postNums) {
result.add(compute(prevNum, postNum, expression.charAt(i)));
}
}
}
// 如果表达式expression中没有包含运算符,就是一个纯数字,那么就直接返回该数字
if (result.isEmpty()) {
result.add(Integer.valueOf(expression));
}
return result;
}
private Integer compute(Integer a, Integer b, char operator) {
if (operator == '+') {
return a + b;
} else if (operator == '-') {
return a - b;
} else if (operator == '*') {
return a * b;
} else {
return null;
}
}
}