题目:
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-1-1"
.
((2-1)-1) = 0 (2-(1-1)) = 2
Output: [0, 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]
解答:
一开始打算用回溯算法。但是如何自顶向下传递当前状态呢?好像很麻烦。
正确的思路应该是自底向上递归:假设已经知道当前子问题的解。这道题中,就是已知左右两部分的可能取值的集合,然后两层循环匹配。
还有个一些细节问题,例如:
如何分割字符串为左右两个部分?string 自带的 substr 用法为:string substr (size_type start = 0, size_type count = npos); 首先,函数的返回值是子串,不修改原字符串;其次,第一个参数是子串在原串中的位置;最后,第二个参数不是子串的结束位置而是子串长度,如果不写默认取到字符串结尾(不论开始点在哪里)。
单个字符转为数字是 num = ch - '0',例子中没有说明如果多位数怎么办?多位数,建议还是使用 C/C++ 自带函数atoi (负数、多位数均可)。但 atoi 的输入是字符指针类型而不是字符串,转换还需要对字符串处理 str.c_str()。
class Solution {
public:
vector<int> diffWaysToCompute(string input) {
int size = input.length();
vector<int> ans;
bool allnumber = true;
vector<int> left, right;
for(int i = 0; i < size; i++) {
if (input[i] >= '0' && input[i] <= '9') continue;
allnumber = false;
left = diffWaysToCompute(input.substr(0, i));
right = diffWaysToCompute(input.substr(i + 1));
if (input[i] == '+') {
for (vector<int>::iterator l = left.begin(); l != left.end(); l++) {
for (vector<int>::iterator r = right.begin(); r != right.end(); r++) {
ans.push_back((*l) + (*r));
}
}
}
else if (input[i] == '-') {
for (vector<int>::iterator l = left.begin(); l != left.end(); l++) {
for (vector<int>::iterator r = right.begin(); r != right.end(); r++) {
ans.push_back((*l) - (*r));
}
}
}
else if (input[i] == '*') {
for (vector<int>::iterator l = left.begin(); l != left.end(); l++) {
for (vector<int>::iterator r = right.begin(); r != right.end(); r++) {
ans.push_back((*l) * (*r));
}
}
}
}
if(allnumber == true) {
ans.push_back(atoi(input.c_str()));
}
return ans;
}
};