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”, “1*2*3”]
“232”, 8 -> [“2*3+2”, “2+3*2”]
“105”, 5 -> [“1*0+5”,”10-5”]
“00”, 0 -> [“0+0”, “0-0”, “0*0”]
“3456237490”, 9191 -> []
分析:题意为在给定的字符串中添加运算符,使得表达式的值等于给定的target。
思路是用深度优先搜索算法,先截取一段数字,将之前的计算结果加上或者减去这个数字,在将新的结果和剩余的数字串带入下一轮搜索中,直到最后结果等于目标值target。将大问题分解成多个小问题,再将所有小问题的解合起来,形成大问题的解,就是分治算法。
注意:
在2+3*4这个表达式中,当计算到3时,后面是号,由四则运算法则需要先算号,所以不能从左到右依次计算,而应该先把3*4的值算出来再和2相加得到结果2+12=14才是正确的。因此需要设定一个变量currRes保存计算到当前数字的结果,在这个例子中是2+3=5,当要处理数字4时,由于前面运算符是*,设定一个变量prevNum保存上一次处理的数字,这个例子中prevNum=3,设定一个变量currNum保存当前处理的数,此处currNum=4,所以带入下一轮搜索的currRes=currRes-prevNum+prevNum*currNum,还要记得更新prevNum的值,这个例子中prevNum=3*4.
若截取到的数字形如”001”的时候需要处理前面的0
public class Solution {
public static List<String> addOperators(String num, int target) {
List<String> res = new LinkedList<String>();
if(num==null || num.length()==0) return res;
helper(res,num, target, "", 0, 0);
return res;
}
private static void helper(List<String> res,String num, int target, String tmp, long currRes, long prevNum){
// 如果计算结果等于目标值,且所有数都用完了,则是有效结果
if(currRes == target && num.length() == 0){
String exp = new String(tmp);
res.add(exp);
return;
}
// 搜索所有可能的拆分情况
for(int i = 1; i <= num.length(); i++){
String currStr = num.substring(0, i);
// 对于前导为0的数予以排除
if(currStr.length() > 1 && currStr.charAt(0) == '0'){
return;
}
// 得到当前截出的数
long currNum = Long.parseLong(currStr);//防止越界
// 去掉当前的数,得到下一轮搜索用的字符串
String next = num.substring(i);
//不是第一个数字
if(tmp.length() != 0){
// 乘法
helper(res,next, target, tmp+"*"+currNum, (currRes - prevNum) + prevNum * currNum, prevNum * currNum);
// 加法
helper(res,next, target, tmp+"+"+currNum, currRes + currNum, currNum);
// 减法
helper(res,next, target, tmp+"-"+currNum, currRes - currNum, -currNum);
} else {
//从第一个数字进行处理
helper(res,next, target, currStr, currNum, currNum);
}
}
}
}