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: "2
3-45"
(2
(3-(45))) = -34
((2
3)-(45)) = -14
((2
(3-4))5) = -10
(2
((3-4)5)) = -10
(((2
3)-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递推方式有一般的有些不同

posted @ 2015-08-09 12:40  卖程序的小歪  阅读(152)  评论(0编辑  收藏  举报