题目描述
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.
题目大意
给定一个只包含0-9的字符串和一个正整数,要求利用二元运算符‘+’,‘-’,‘*’(注意,这些都是二元运算符,并不是一元运算符,也就是说不能有负数)计算出能够等于所给整数的可能的运算式。
示例
E1
E2
E3
E4
E5
解题思路
依次进行递归运算,递归的时候分别进行不同的三种运算,当递归遍历到字符串末尾时,判断生成的结果是否为target,若是则产生一个结果,进行保存。
由于运算符中有惩罚,因此在进行乘法运算的时候要注意前一个运算符是否为乘法,若不是则要重新计算运算,因为乘法运算优先级高于加法与减法。
复杂度分析
时间复杂度:O(N2)
空间复杂度:O(N)
代码
class Solution { public: vector<string> addOperators(string num, int target) { vector<string> res; if(num.empty()) return res; // 依次遍历字符串,将第一个数字表示出来 for(int i = 1; i <= num.length(); ++i) { string s = num.substr(0, i); // 将第一个数字转为long类型 long n = stol(s); // 若该字符串包含前缀零,则继续 if(to_string(n).size() != s.size()) continue; // 进行dfs递归 dfs(res, num, target, s, i, n, n, '#'); } return res; } // res:最终结果数组 // num:给定的数字字符串 // target:目标结果 // ans:递归当前的计算式 // pos:当前遍历到字符串的位置 // pt:之前计算式的总和 // pn:上一个操作数的值 // op:上一个操作符 void dfs(vector<string>& res, const string num, const int target, string ans, int pos, long pt, long pn, char op) { // 若满足条件将该算术式加入结果数组 if(pos == num.size() && pt == target) res.push_back(ans); // 否则进行递归调用 else { // 遍历剩余数组 for(int i = pos + 1; i <= num.size(); ++i) { string tmp = num.substr(pos, i - pos); // 将pos-i之间的字符串转为数字 long tmpnum = stol(tmp); if(to_string(tmpnum).size() != tmp.size()) continue; // 若上一个运算符为‘+’号,则进行正常运算 dfs(res, num, target, ans + '+' + tmp, i, pt + tmpnum, tmpnum, '+'); // 若上一个运算符为‘-’号,则进行正常运算 dfs(res, num, target, ans + '-' + tmp, i, pt - tmpnum, tmpnum, '-'); // 若上一个运算符为‘*’号,需要进行判断上一个为运算符的符号,分别进行不同的运算 dfs(res, num, target, ans + '*' + tmp, i, (op == '+') ? pt - pn + pn * tmpnum : ((op == '-') ? pt + pn - pn * tmpnum : pn * tmpnum), tmpnum * pn, op); } } } };