Description
Given a string that contains only digits 0-9
and a target value, return all possibilities to add binary operators (not unary) +
, -
, or *
between the digits so they evaluate to the target value.
Examples:
"123", 6 -> ["1+2+3", "123"]
"232", 8 -> ["23+2", "2+32"]
"105", 5 -> ["10+5","10-5"]
"00", 0 -> ["0+0", "0-0", "00"]
"3456237490", 9191 -> []
Credits:
Special thanks to @davidtan1890 for adding this problem and creating all test cases.
Solution
DFS, time O(4 ^ n), space O(n)
这道题应该只能用穷举法去做,在每两个数字间隔的位置上,都有加减乘以及没有运算符四种选择。可是如何穷举呢?必须用DFS或者说backtrack才行。
几个值得注意的地方:
- 无论是在最底层将path添加到结果集中,还是在上层拼接结果,应该都是可以的,下面的解法采用的是第一种,代码写起来更简洁;
- 为什么需要target, eval, multi这几个变量呢?考虑连续乘法的情况,例如1 + 2 * 3 * 4 - 5,在计算到4的时候,做乘法它需要知道前面2 * 3的结果,在这里就用multi来表示。而eval在这里表示1 + 2 * 3的结果。这样最后只需要判断target == eval即可。
- 特别需要注意的是,以0开头的数字是非法的!
- 另外还需要注意中间结果可能会overflow,需要用long存储以避免这个问题。
总之是道挺难的题,查缺补漏了。
class Solution {
public List<String> addOperators(String num, int target) {
List<String> res = new ArrayList<>();
if (num == null || num.isEmpty()) {
return res;
}
dfs(num.toCharArray(), 0, target, 0, 0, "", res);
return res;
}
public void dfs(char[] arr, int start, int target, long eval, long multi
, String path, List<String> res) {
if (start == arr.length) {
if (target == eval) {
res.add(path);
}
return;
}
long curr = 0;
for (int i = start; i < arr.length; ++i) {
if (i > start && arr[start] == '0') { // leading zeros in a number is illegal
break;
}
curr = 10 * curr + arr[i] - '0';
if (start == 0) { // path is empty now, add curr by default
dfs(arr, i + 1, target, eval + curr, curr, path + curr, res);
} else {
dfs(arr, i + 1, target, eval + curr, curr, path + "+" + curr, res);
dfs(arr, i + 1, target, eval - curr, -curr, path + "-" + curr, res);
dfs(arr, i + 1, target, eval - multi + multi * curr
, multi * curr, path + "*" + curr, res);
}
}
}
}