Copy Input:
num = "123",
target = 6
Output:
["1+2+3", "1*2*3"]
Copy Input:
num = "232",
target = 8
Output:
["2*3+2", "2+3*2"]
Copy Input:
num = "105",
target = 5
Output:
["1*0+5","10-5"]
Copy Input:
num = "00",
target = 0
Output:
["0+0", "0-0", "0*0"]
Copy Input:
num = "3456237490",
target = 9191
Output:
[]
Copy 流程:
1. dfs + backtracking 思路
2. dfs 函数中存 "左面表达式的当前值" 和 "上一步操作的结果" (用于处理优先级)
3. 参数都用 Long,防止溢出,毕竟 String 可能是个大数
4. 如果 start 位置是 0 而且当前循环的 index 还是 0,直接 return,因为一轮循环只能取一次 0;
5. start == 0 的时候,直接考虑所有可能的起始数字扔进去,同时更新 cumuVal 和 prevVal;
6. 除此之外,依次遍历所有可能的 curVal parse,按三种不同的可能操作做 dfs + backtracking;
- 加法:直接算,prevVal 参数传 curVal,代表上一步是加法;
- 减法:直接算,prevVal 参数传 -curVal,代表上一步是减法;
- 乘法:要先减去 prevVal 抹去上一步的计算,然后加上 prevVal curVal 代表当前值;
同时传的 preVal 参数也等于 prevVal curVal.
- 乘法操作这种处理方式,在遇到连续乘法的时候可以看到是叠加的;但是前一步操作如果不是乘法,则可以优先计算乘法操作。
10-5-2x6 ,遇到乘法之前是 cumuVal = 3, preVal = -2;
新一轮 dfs 时 curVal = 6, 先退回前一步操作 - prevVal,得到 5,
其实就是之前 (10 - 5) 的结果,然后加上当前结果 (-2 x 5),prevVal 设成 -10 传递过去即可。
Copy class Solution {
public List<String> addOperators(String num, int target) {
List<String> res = new ArrayList<>();
dfs(num, target, res, "", 0, 0, 0);
return res;
}
private void dfs(String num, int target, List<String> res,
String s, long sum, long lastValue, int start) {
if (start == num.length()) {
if (sum == target) {
res.add(s);
}
return;
}
for (int i = start; i < num.length(); i++) {
if (i != start && num.charAt(start) == '0') {
break;
}
long curr = Long.parseLong(num.substring(start, i + 1));
if (start == 0) {
dfs(num, target, res, "" + curr, curr, curr, i + 1);
} else {
dfs(num, target, res, s + "*" + curr,
sum + curr * lastValue - lastValue, curr * lastValue, i + 1); //minus last and add *
dfs(num, target, res, s + "+" + curr, sum + curr, curr, i + 1);
dfs(num, target, res, s + "-" + curr, sum - curr, -curr, i + 1);
}
}
}
}