题干
原题网址:
https://leetcode.com/problems/different-ways-to-add-parentheses/description/
题干解析
给你一个算式(string类型),让你无视已有的操作符优先级,求出所有操作符运算顺序得到的结果,返回一个vector。(看上图例子更加清楚)
知识点
分治、字符串处理
难度
中等
解题思路
这道题可以用分治思想来解决。对于每一个有多个操作符的运算式子,不管哪种运算顺序,总有一个操作符是最后运算的。我们可以选择一个运算符当做最后运算,以其为中心,把原式分解为左右两个子串。递归调用函数,分别算出左右子串可以得到的结果集合,再将得到的左子串的每一个答案,和右子串的每一个答案,通过刚刚的中心的操作符进行运算,得到结果。函数实现时,加上递归终止条件的判断–运算式的操作符只剩下1个或者0个,剩下的就是对字符串的处理了。循环遍历,让式子中的每个操作符都充当一次最后运算的操作符,得到的结果合并后就是最终我们要的结果。
代码
class Solution {
public:
vector<int> diffWaysToCompute(string input) {
int op = 0; //用来标志算式中地操作符地个数
vector<int> op_index; //用来指示各个操作符在字符串中的下标
vector<int> ans; //用来存放结果
for (int i = 0; i < input.size(); i++) { //遍历字符串,得出操作符的个数和下标
if (input[i] == '-' || input[i] == '+' || input[i] == '*') {
op++;
op_index.push_back(i);
}
}
if (op == 1) { //如果只有一个操作符,直接处理字符串,得到唯一的算是结果
int left = 0, right = 0;
int tenth = 0;
for (int i = op_index[0] - 1; i >= 0; i--) { //处理字符串,将操作符左边的部分转化成对应的数字
left += (input[i] - '0') * pow(10, tenth);
tenth++;
}
tenth = 0;
for (int i = input.size() - 1; i > op_index[0]; i--) {//处理字符串,将操作符右边的部分转化成对应的数字
right += (input[i] - '0') * pow(10, tenth);
}
switch (op_index[0]) { //根据操作符,将左右两个数运算,得到结果
case '+':
ans.push_back(left + right);
return ans;
case '-':
ans.push_back(left - right);
return ans;
case '*':
ans.push_back(left * right);
return ans;
}
} else if (op == 0) { //如果没有操作符
if (input.size() == 0) {//如果是空串,返回空
return ans;
} else { //不是空串又没有操作符,说明是一个纯数字,直接对字符串处理得到答案
int temp_ans = 0;
int tenth = 0;
for (int i = input.size() - 1; i >= 0; i--) {
temp_ans += (input[i] - '0') * pow(10, tenth);
tenth++;
}
ans.push_back(temp_ans);
return ans;
}
}
for (int i = 0; i < op; i++) { //遍历每种“选择一个操作符用在最后运算”的情况,即每个运算符被选中当做最后运算的运算符的情况
vector<int> left = diffWaysToCompute(input.substr(0, op_index[i])); //递归得到左子串可以运算出的结果集合
vector<int> right = diffWaysToCompute(input.substr(op_index[i] + 1, input.size() - op_index[i])); //递归得到右子串可以运算出的结果集合
for (int j = 0; j < left.size(); j++) { // 对于左子串的每个结果
for (int k = 0; k < right.size(); k++) { //结合右子串的每个结果
switch (input[op_index[i]]) { //根据运算符进行运算
case '+':
ans.push_back(left[j] + right[k]);
break;
case '-':
ans.push_back(left[j] - right[k]);
break;
case '*':
ans.push_back(left[j] * right[k]);
break;
default:
cout<<"error"<<endl;
break;
}
}
}
}
return ans;
}
};