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 ) ;
}
}
}
}