1、题目
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 *.
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
((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]
题目大意:给定一个式子,求出所有按不同加括号的结果
2、分治体现
先看一个例子:2+1,不难发现,操作符左右两边分别是一个数,然后进行运算,因此,
无论运算式子多长都可以看成 A+B 这样的形式,A、B也可继续以同样的方式分下去
总之,
所有的操作都是相同的一种形式,因此本题可以递归求解,把操作符两边不断细分,直到操作符 left 和 right 只剩下一个数
3、解题思路
不同结果,说白了就是人为规定操作符运算次序导致的,【(*1)-(*2)】 , 【-(*1)(*2)】 。。。等,*1、*2是两个乘法。因此,解法思想归纳如下:
(1)得到操作符
(2)进入递归,得到操作符左右的数字,left 和 right
(3)left 和 right按照操作符进行运算
为了实现操作符不同次序的效果,可以遍历字符串,每得到一个操作符就进入递归,每次递归以该次遍历到的操作符划分左右
4、代码如下
class Solution {
public:
//to check wether the str is the original one [1]
bool no(string str) {
bool no1 = false;
for (int i = 0; i < str.size(); i++)
if (str[i] == '+' || str[i] == '-' || str[i] == '*')
no1 = true;
return no1;
}
//do the main job but get a vector out of order [2]
vector<int> diffWaysToCompute2(string input) {
vector<int> ret;
for (int i = 0; i < input.size(); i++)
{
if (input[i] == '+' || input[i] == '-' || input[i] == '*')
{
vector<int> left = diffWaysToCompute2(input.substr(0, i));
vector<int> right = diffWaysToCompute2(input.substr(i + 1, input.size()-i-1));
//////////[3]
for (int y = 0; y < left.size();y++) {
for (int u = 0; u < right.size(); u++) {
if (input[i] == '+')
ret.push_back(left[y] + right[u]);
else if (input[i] == '-')
ret.push_back(left[y] - right[u]);
else
ret.push_back(left[y] * right[u]);
}
}
}
}
///////[4]
if (input.size() >= 1 && !no(input)) {
int te = 0;
int allsize = input.size() - 1;
for (int f = 0; f < input.size(); f++) {
int gg = input[f] - '0';
gg *= pow(10, allsize--);
te += gg;
}
ret.push_back(te);
}
return ret;
}
//the right answer with a ordered vector [5]
vector<int> diffWaysToCompute(string input) {
vector<int> temp = diffWaysToCompute2(input);
sort(temp.begin(), temp.end());
return temp;
}
};
对代码进一步说明:
注释【1】:这是为了递归基准备的,要结束递归的条件是:字符串只剩一个数字了,也就是 input.size() >= 1 && !no(input) :字符串size不小于一,且无操作符在其中(第一次提交被坑了,以为number只包括 0——9,显然不是)
注释【2】:没什么好说的
注释【3】:对应解题思路的步骤(3),但是为什么是一个嵌套循环呢?原先我写的是 left【0】+/-/* right【0】,后来发现结果少了几个,原因如下,举例 {2*3-4*5},当遍历这个字符串到 input【5】时,它最开始的 left 是 2*3-4,接下来遍历这个,会发现,由于包含两个操作符 *和-,根据不同顺序,得到的 left 会有两个值 2 和 -2,right同理
注释【4】:for 循环为了实现多位数从字符到int的转换
注释【5】:排序,用了sort 函数
最后,本文思路受以下博客启发,表示感谢!