LeetCode : Different Ways to Add Parentheses
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: "23-45"
(2(3-(45))) = -34
((23)-(45)) = -14
((2(3-4))5) = -10
(2((3-4)5)) = -10
(((23)-4)*5) = 10
Output: [-34, -14, -10, -10, 10]
这题有点类似算24点,不过比算24点得题目应该是简单,先直接使用暴力dfs搜索:
class Solution {
private:
vector<int> operands;
vector<char> operators;
public:
vector<int> diffWaysToCompute(string input) {
parse(input);
return dfs(0, operands.size());
}
vector<int> dfs(int start, int end) {
vector<int> res;
if (start >= end) {
return res;
}
if (start + 1 == end) {
res.push_back(operands[start]);
return res;
}
for (int i=start + 1; i<end; i++) {
vector<int> left = dfs(start, i);
vector<int> right= dfs(i, end);
for (int l : left) {
for (int r: right) {
res.push_back(cal(operators[i-1], l, r));
}
}
}
return res;
}
int cal(char op, int a, int b) {
switch(op) {
case '+': return a+b;
case '-': return a-b;
case '/': return a/b;
case '*': return a*b;
}
return 0;
}
void parse(string& input) {
int pos = 0;
int len = input.size();
int stage = 0;
for(;;) {
// skip spaces
while (pos < len && input[pos] == ' ') {
pos++;
}
if (pos >= len) {
break;
}
if (stage == 0) {
// stage == 0, to read in a number
bool neg = false;
if (input[pos] == '-' || input[pos] == '+') {
neg = input[pos] == '-';
pos++;
}
if (input[pos] < '0' || input[pos] > '9') {
printf("invalid input, operand format error.\n");
break;
}
int value = 0;
while (pos < len && input[pos] >= '0' && input[pos] <= '9') {
value = value * 10 + input[pos++] - '0';
}
if (neg) {
value = -value;
}
operands.push_back(value);
stage = 1;
continue;
}
if (stage == 1) {
// stage == 1, to read in an operator
char op = input[pos];
if (op == '-' || op == '*' || op == '/' || op == '+') {
operators.push_back(op);
pos++;
} else {
printf("invalid input, operator format error.\n");
break;
}
stage = 0;
continue;
}
printf("invalid parsing stage.\n");
break;
}
if (operators.size() != operands.size() - 1) {
printf("invalid input, operands not match with operators.\n");
}
}
};
这里解析输入的部分使用自己编写的函数,如果允许的话可以使用C++的istringstream类来解析如下:
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
int main() {
vector<int> operands;
vector<char> operators;
string input = "2-1-1";
istringstream ss(input + "+");
int num;
char op;
while (ss >> num && ss >> op) {
operands.push_back(num);
operators.push_back(op);
}
operators.pop_back();
for (int i: operands) {
cout<<i<<endl;
}
for (char ch : operators) {
cout<<ch<<endl;
}
return 0;
}
另外一个dp解法:
class Solution {
private:
vector<int> operands;
vector<char> operators;
public:
vector<int> diffWaysToCompute(string input) {
parse(input);
int dlen = operands.size();
vector<vector<vector<int>>> dp(dlen, vector<vector<int>>(dlen));
for (int i=0; i<dlen; i++) {
for (int j=i; j>=0; j--) {
if (i == j) {
dp[j][i].push_back(operands[i]);
continue;
}
for (int k = j; k < i; k++) {
auto left = dp[j][k];
auto right= dp[k + 1][i];
for (auto a: left) {
for (auto b: right) {
dp[j][i].push_back(cal(operators[k], a, b));
}
}
}
}
}
return dp[0][dlen - 1];
}
// cal & parse function see codes above
}
这一类的DP递推方式有一般的有些不同