Given a string that contains only digits 0-9
and a target value, return all possibilities to add binaryoperators (not unary) +
, -
, or *
between the digits so they evaluate to the target value.
Example 1:
Input: num =
"123", target = 6
Output: ["1+2+3", "1*2*3"]
Example 2:
Input: num =
"232", target = 8
Output: ["2*3+2", "2+3*2"]
Example 3:
Input: num =
"105", target = 5
Output: ["1*0+5","10-5"]
Example 4:
Input: num =
"00", target = 0
Output: ["0+0", "0-0", "0*0"]
Example 5:
Input: num =
"3456237490", target = 9191
Output: []
Credits:
Special thanks to @davidtan1890 for adding this problem and creating all test cases.
這道題給了我們一個只由數字組成的字符串,讓我們再其中添加+,-或*號來形成一個表達式,該表達式的計算和為給定了target值,讓我們找出所有符合要求的表達式來。看了題目中的例子1和2,很容易讓人誤以為是必須拆成個位數字,其實不是的,比如例子3中的 "105", 5能返回"10-5",說明連着的數字也可以。如果非要在過往的題中找一道相似的題,我覺得跟 Combination Sum II 很類似。不過這道題要更復雜麻煩一些。還是用遞歸來解題,我們需要兩個變量diff和curNum,一個用來記錄將要變化的值,另一個是當前運算后的值,而且它們都需要用 long 型的,因為字符串轉為int型很容易溢出,所以我們用長整型。對於加和減,diff就是即將要加上的數和即將要減去的數的負值,而對於乘來說稍有些復雜,此時的diff應該是上一次的變化的diff乘以即將要乘上的數,有點不好理解,那我們來舉個例子,比如 2+3*2,即將要運算到乘以2的時候,上次循環的 curNum = 5, diff = 3, 而如果我們要算這個乘2的時候,新的變化值diff應為 3*2=6,而我們要把之前+3操作的結果去掉,再加上新的diff,即 (5-3)+6=8,即為新表達式 2+3*2 的值,有點難理解,大家自己一步一步推算吧。
還有一點需要注意的是,如果輸入為"000",0的話,容易出現以下的錯誤:
Wrong:["0+0+0","0+0-0","0+0*0","0-0+0","0-0-0","0-0*0","0*0+0","0*0-0","0*0*0","0+00","0-00","0*00","00+0","00-0","00*0","000"]
Correct:["0*0*0","0*0+0","0*0-0","0+0*0","0+0+0","0+0-0","0-0*0","0-0+0","0-0-0"]
我們可以看到錯誤的結果中有0開頭的字符串出現,明顯這不是數字,所以我們要去掉這些情況,過濾方法也很簡單,我們只要判斷長度大於1且首字符是‘0’的字符串,將其濾去即可,參見代碼如下:
class Solution { public: vector<string> addOperators(string num, int target) { vector<string> res; helper(num, target, 0, 0, "", res); return res; } void helper(string num, int target, long diff, long curNum, string out, vector<string>& res) { if (num.size() == 0 && curNum == target) { res.push_back(out); return; } for (int i = 1; i <= num.size(); ++i) { string cur = num.substr(0, i); if (cur.size() > 1 && cur[0] == '0') return; string next = num.substr(i); if (out.size() > 0) { helper(next, target, stoll(cur), curNum + stoll(cur), out + "+" + cur, res); helper(next, target, -stoll(cur), curNum - stoll(cur), out + "-" + cur, res); helper(next, target, diff * stoll(cur), (curNum - diff) + diff * stoll(cur), out + "*" + cur, res); } else { helper(next, target, stoll(cur), stoll(cur), cur, res); } } } };
類似題目:
Evaluate Reverse Polish Notation
Different Ways to Add Parentheses
參考資料:
https://leetcode.com/problems/expression-add-operators/
https://leetcode.com/problems/expression-add-operators/discuss/71971/Accepted-C%2B%2B-Solution