题目
题目给出一个算式,包含加减乘三种运算,要求返回在所有可能的位置添加括号后的运算结果,结果可以重复。比如输入“2*3-4*5\” ,输出为[-34, -14, -10, -10, 10]。
分析
在任意一个数或一个算式都可以添加括号优先计算括号里的值,可以采用分治法,每个运算符前后都可以分为两个子问题,两个子问题的结果再根据预算符做运算,就能得出总的结果。子问题可以越分越小,最终只包含一个单独的数字,那么这个数字就是最小的子问题的解。
实现
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
using namespace std;
class Solution {
unordered_map<string, vector<int> > result;
public:
vector<int> diffWaysToCompute(string input) {
if (result.count(input) != 0)
return result[input];
vector<int> res;
char op;
for (unsigned int i = 0; i < input.size(); ++i) {
if (input[i] == '+' || input[i] == '-' || input[i] == '*') {
op = input[i];
vector<int> l = diffWaysToCompute(input.substr(0, i));
vector<int> r = diffWaysToCompute(input.substr(i + 1));
for (const int a : l) {
for (const int b : r) {
if (op == '+')
res.push_back(a + b);
else if (op == '-')
res.push_back(a - b);
else if (op == '*')
res.push_back(a * b);
}
}
}
}
if (res.empty())
res.push_back(stoi(input));
return result[input] = res;
}
};
其实按照分析中的做法,题目就可以解决,然而考虑到这样做可能会处理大量重复子问题,所以在实现时有加入了类似动态规划的做法,将每次运行的结果放入一个unordered_map中,用空间换取时间,在算式较长的情况下效果显著,但可能是由于LeetCode上的测试用例比较简单,加入记忆化搜索后时间保持不变。