LC282. Expression Add Operators
给一串数字,在数字之间添加二元运算符 + - * ,使表达式的运算结果为 target ,输出所有可能的添加方式。
DFS:设共有 n 个数字,共有 n-1 个中间位置需要插入符号,插入的符号为:
''(0) '+'(1) '-'(2) '*'(3)
插入''(0)表示不插入数字,即相邻的数字组成更大的数字,每个位置有4中插法,共有$4^{n-1}$种插法,NP问题,只能用dfs暴力搜索。
每得到一个插满符号的表达式,需要计算表达式的值,与 target 比较。
计算表达式的值:用一个符号栈(单调栈,栈底符号优先级低)和一个值栈来计算,符号栈中最多只能有2个符号+/- 和*,同优先级都存在时需要计算出相应结果再入栈。
此题可以在插入符号的同时计算表达式的值,速度更快,方法如下:
class Solution { public: typedef long long LL; vector<string> ans; vector<int> nu; vector<int> nop; int n, tar; // 0 '' 1 '+' 2 '-' 3 '*' void dfs(int cur, int op1, int op2, LL n1, LL n2, LL n3, int zero) { if (cur == n - 1) { if (op2) n2 *= n3; if (op1 == 1) n1 += n2; else n1 -= n2; if (n1 == tar) { string s; for (int i = 0; i < n - 1; ++i) { s += to_string(nu[i]); if (nop[i] == 1) s += '+'; else if (nop[i] == 2) s += '-'; else if (nop[i] == 3) s += '*'; } s += to_string(nu[n - 1]); ans.push_back(s); } return; } cur++; int v = nu[cur]; // 0 '' if (!zero) { nop[cur - 1] = 0; if (op2) dfs(cur, op1, op2, n1, n2, n3 * 10 + v, 0); else dfs(cur, op1, op2, n1, n2 * 10 + v, 0, 0); } // 3 '*' nop[cur - 1] = 3; if (op2) n2 *= n3, n3 = 0; dfs(cur, op1, 3, n1, n2, v, v == 0); // 1 '+' nop[cur - 1] = 1; if (op1 == 1) n1 += n2, n2 = 0; else n1 -= n2, n2 = 0; dfs(cur, 1, 0, n1, v, 0, v == 0); // 2 '-' nop[cur - 1] = 2; dfs(cur, 2, 0, n1, v, 0, v == 0); } vector<string> addOperators(string num, int target) { for (char c : num) nu.push_back(c - '0'); n = nu.size(); if (n == 0) return ans; tar = target; nop.assign(n, 0); dfs(0, 1, 0, 0, nu[0], 0, nu[0] == 0); return ans; } };