Problem
Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators. The valid operators are +, - and *.
Example 1
Input: “2-1-1”.
((2-1)-1) = 0
(2-(1-1)) = 2
Output: [0, 2]
Example 2
Input: “2*3-4*5”
(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
Output: [-34, -14, -10, -10, 10].
Solution
题意
输入一个运算式,求出所有可能的加括号的方式,并计算出结果。结果存储在一个vector里。
分析
刚看到题有种不知道怎么下手的感觉,因为是在分治算法分类下,所以还是从分治的角度来考虑问题。
参阅了网上的一些解法,一开始有点看不懂代码,但是看了一段Python的伪代码之后就豁然开朗,这里先贴上这段Python伪代码:
def solve(input):
if input is digit:
return [input]
ans = [ ]
for x in input:
if x is operator:
left = solve(input[0 ~ x])
right = solve(input[x + 1 ~ len])
for l in left:
for r in right:
ans += [ calc(l, r, x) ]
return ans
简单说明一下这段代码:
1. 如果输入只有一位(即只有一个数字),直接返回数字。
2. 从input[0]开始遍历整个string,如果input[I]是运算符,则以input[i]为界,分成左右两个子串,递归调用solve函数,返回的结果分别构成左右两个vector
3. 接下来是两重循环,遍历左右vector中的元素,判断当前元素input[i]的符号,将left[j]和right[k]的运算结果push进result这个容器里。
4. 返回result,算法结束。
Code
class Solution {
public:
vector<int> diffWaysToCompute(string input) {
vector<int> result;
int size = input.size();
for (int i = 0; i < size; i++){
//以input[i]为界,分为左右两个子串
if (input[i] == '+' || input[i] == '-' || input[i] == '*'){
vector<int> left = diffWaysToCompute(input.substr(0, i));
vector<int> right = diffWaysToCompute(input.substr(i + 1));
int leftSize = left.size();
int rightSize = right.size();
for (int j = 0; j < leftSize; j++){
for (int k = 0; k < rightSize; k++){
if (input[i] == '+') {
result.push_back(left[j] + right[k]);
}
else if (input[i] == '-') {
result.push_back(left[j] - right[k]);
}
else if (input[i] == '*') {
result.push_back(left[j] * right[k]);
}
}
}
}
}
if (result.empty()){
//处理输入只有一个数字的情况
result.push_back(atoi(input.c_str()));
}
return result;
}
};