题目地址:
https://www.lintcode.com/problem/expression-add-operators/description
给定一个只含数字的字符串 s s s,除了开头之外,其余位置可以插入加号、减号或者乘号成为一个合法的表达式。再给点一个数 t t t,要求返回所有算出来的值恰好等于 t t t的表达式。注意,每个数都不能有前导 0 0 0。
思路是DFS。枚举每个位置截取数字,截取的时候注意不能有前导 0 0 0。如果在开头,则直接截取数字,然后进入下一层递归;如果不在开头,则不但要截取数字,而且还需要枚举进行三种不同的运算,由于有乘法运算的存在,它的优先级比加减法要高,所以要将做乘法的因子也要作为参数在递归的时候传递下去。例如,在枚举 a + b × c a+b\times c a+b×c的时候,要把 b × c b\times c b×c传递下去,这样在枚举乘法的时候,可以先将这个因子删掉,然后再加上这个因子乘以枚举的数,比如枚举了 d d d,那么就计算 a + ( b × c ) − ( b × c ) + ( b × c ) × d a+(b\times c)-(b\times c)+(b\times c)\times d a+(b×c)−(b×c)+(b×c)×d,这样就能处理优先级的问题。代码如下:
import java.util.ArrayList;
import java.util.List;
public class Solution {
/**
* @param num: a string contains only digits 0-9
* @param target: An integer
* @return: return all possibilities
*/
public List<String> addOperators(String num, int target) {
// write your code here
List<String> res = new ArrayList<>();
dfs(0, new StringBuilder(), 0, 0, num, target, res);
return res;
}
private void dfs(int pos, StringBuilder sb, long cur, long last, String s, int target, List<String> res) {
// 如果枚举到了s的最后,则枚举完了,看一下算出来的结果是否是target
if (pos == s.length()) {
if (cur == target) {
res.add(sb.toString());
}
return;
}
// 开始截取数字
for (int i = pos; i < s.length(); i++) {
String num = s.substring(pos, i + 1);
// 如果有前导0则略过
if (num.length() > 1 && num.charAt(0) == '0') {
continue;
}
// 解析一下数字
long curNum = Long.parseLong(num);
// 按枚举的是不是第一个数字来分类
if (pos == 0) {
// 如果是第一个数字,那么直接append,进入下一层递归
sb.append(num);
dfs(i + 1, sb, curNum, curNum, s, target, res);
sb.setLength(sb.length() - num.length());
} else {
// 如果不是第一个数字,就需要枚举三种运算
sb.append('+').append(curNum);
dfs(i + 1, sb, cur + curNum, curNum, s, target, res);
// 回溯的时候恢复现场。注意,除了把运算符删掉之外,还需要把num本身的长度也给删掉
sb.setLength(sb.length() - 1 - num.length());
sb.append('-').append(curNum);
dfs(i + 1, sb, cur - curNum, -curNum, s, target, res);
sb.setLength(sb.length() - 1 - num.length());
sb.append('*').append(curNum);
dfs(i + 1, sb, cur - last + last * curNum, last * curNum, s, target, res);
sb.setLength(sb.length() - 1 - num.length());
}
}
}
}
时间复杂度是指数级,空间 O ( l s ) O(l_s) O(ls)。