282. Expression Add Operators
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 -> []
时间 O(N^2) 空间 O(N)
因为要输出所有可能的情况,必定是用深度优先搜索。问题在于如何将问题拆分成多次搜索。加减法很好处理,每当我们截出一段数字时,将之前计算的结果加上或者减去这个数,就可以将剩余的数字字符串和新的计算结果代入下一次搜索中了,直到我们的计算结果和目标一样,就完成了一次搜索。然而,乘法如何处理呢?这里我们需要用一个变量记录乘法当前累乘的值,直到累乘完了,遇到下一个加号或减号再将其算入计算结果中。这里有两种情况:
乘号之前是加号或减号,例如2+3*4
,我们在2那里算出来的结果,到3的时候会加上3,计算结果变为5。在到4的时候,因为4之前我们选择的是乘号,这里3就应该和4相乘,而不是和2相加,所以在计算结果时,要将5先减去刚才加的3得到2,然后再加上3乘以4,得到2+12=14
,这样14就是到4为止时的计算结果。
另外一种情况是乘号之前也是乘号,如果2+3*4*5
,这里我们到4为止计算的结果是14了,然后我们到5的时候又是乘号,这时候我们要把刚才加的3*4给去掉,然后再加上3*4*5
,也就是14-3*4+3*4*5=62
。这样5的计算结果就是62。
因为要解决上述几种情况,我们需要这么几个变量,一个是记录上次的计算结果currRes
,一个是记录上次被加或者被减的数prevNum
,一个是当前准备处理的数currNum
。当下一轮搜索是加减法时,prevNum
就是简单换成currNum
,当下一轮搜索是乘法时,prevNum
是prevNum
乘以currNum
。
然后用
int to_int(string s)
{
stringstream ss;
ss << s;
int i;
ss >> i;
return i;
}
就对了!所以 string to int 还是得自己写。用c语言的atoi有的时候会出问题。
class Solution {
public:
vector addOperators(string num, int target)
{
helper(num, target, "", 0, 0);
return ret;
}
private:
vector ret;
void helper(string num, int target, string tmp, long long currRes, long long prevNum)
{
if (currRes == target && num.size() == 0)
{
ret.push_back(tmp);
return;
}
//搜索所有可能的拆分
for (int i = 1; i <= num.size(); i++)
{
string currstr = num.substr(0, i);
//去除前面是0的情况
if (currstr.size() > 1 && currstr[0] == '0')
return; //因为后面肯定也是首位是'0'
//得到当前截出来的数
long long currnum = to_int(currstr);
//去掉当前的数,得到下一轮搜索用的字符串
string next = num.substr(i);
//如果不是第一个字母时,可以加运算符,否则只加数字
if (tmp.size() != 0)
{
helper(next, target, tmp+"*"+currstr, (currRes - prevNum) + prevNum * currnum, prevNum * currnum);
helper(next, target, tmp+"+"+currstr, currRes + currnum, currnum);
helper(next, target, tmp+"-"+currstr, currRes - currnum, -currnum);
}
else
{
helper(next, target, currstr, currnum, currnum); //第一个数
}
}
}
int to_int(string s)
{
stringstream ss;
ss << s;
int i;
ss >> i;
return i;
}
};