给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含 +, - 以及 * 。
示例 1:
输入: "2-1-1"
输出: [0, 2]
解释:
((2-1)-1) = 0
(2-(1-1)) = 2
示例 2:
输入: "2*3-4*5"
输出: [-34, -14, -10, -10, 10]
解释:
(2*(3-(4*5))) = -34
((2*3)-(4*5)) = -14
((2*(3-4))*5) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
思路:遍历字符串,对每一个遇到的运算符左右两边的表达式加上括号。表达式变为:(左边的表达式left)操作符op(右边的表达式right)。求出‘left’的所有的结果,‘right’的所有的结果,两边所有的结果都匹配一次,就是op的优先级为最低时,表达式所有的值。‘left’的的所有结果和‘right’所有结果也是这么递归出来的。题解中用了备忘录mp,减少重复子问题的计算。
vector<int> diffWaysToCompute(string expression)
{
map<string, vector<int>> mp;
return helper(expression, mp);
}
vector<int> helper(string str, map<string, vector<int>> mp)
{
vector<int> res;
int len = str.size();
for (int i = 0; i < len; i++)
{
if (str[i] == '+' || str[i] == '-' || str[i] == '*')
{
vector<int> resleft, resright;
string left = str.substr(0, i);
if (mp.find(left) != mp.end())
{
resleft = mp[left];
}
else
{
resleft = helper(left, mp);
}
string right = str.substr(i + 1);
if (mp.find(right) != mp.end())
{
resright = mp[right];
}
else
{
resright = helper(right, mp);
}
for (auto l : resleft)
{
for (auto r : resright)
{
if (str[i] == '+')
{
res.push_back(l + r);
}
else if (str[i] == '-')
{
res.push_back(l - r);
}
else
{
res.push_back(l * r);
}
}
}
}
}
if (res.empty())
{
res.push_back(stoi(str));
}
mp[str] = res;
return res;
}