Leetcode-241.Different Ways to Add Parentheses

Problem Description:
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
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]


Analysis:
The problem seems to be little hard at first glance. However the hashtag hint that it’s an easy way to apply divide and conquer method.
The idea is : when encounter an operator, we split the string to two parts. One left to the operator and the other right to it. Then we recursively compute the all possible result for each part. At last we just need combine the two parts’ result based on the operator. Careful the string only contains operand.

Recursive:

vector<int> diffWaysToCompute(string input) {
        vector<int> res;
        int n = input.size();
        for (int i = 0; i < n; i++ )
        {
            char c = input[i];
            if (ispunct(c)){
                 // Split input string into two parts and solve them recursively
                vector<int> res1 = diffWaysToCompute(input.substr(0, i));
                vector<int> res2 = diffWaysToCompute(input.substr(i+1));
            for (auto op1 : res1)
                for (auto op2 : res2){
                    if (c == '+')
                        res.push_back(op1 + op2);
                    else if (c == '-')
                        res.push_back(op1 - op2);
                    else 
                        res.push_back(op1 * op2);
                }
            }
        }
            if (res.empty()) 
                //res.push_back(atoi(input.c_str());
                res.push_back(stoi(input));
            return res;
    }

Top down & Memorization method (not dp) :

class Solution {
public:
vector<int> diffWaysToCompute(string input) 
{
    unordered_map <string, vector<int> > memo;
    return Compute(memo, input);
}

vector<int> Compute(unordered_map<string, vector<int> > & memo, string input)
{
    vector<int> res;
    for (int i = 0; i < input.size(); ++i)
    {
        vector<int> res1, res2;
        if (ispunct(input[i]))
        {
        string left = input.substr(0, i);
        if (memo[left].size() > 0) 
             res1 = memo[left];
        else 
             res1 = Compute(memo, left);
        string right = input.substr(i + 1);
        if (memo[right].size() > 0)
            res2 = memo[right];
        else 
            res2 = Compute(memo, right);
        for (auto r1 : res1)
            for (auto r2 : res2)
            {
                if (input[i] == '+')
                    res.push_back(r1 + r2);
                else if (input[i] == '-')
                    res.push_back(r1 - r2);
                else res.push_back(r1 * r2);
            }
        }
    }
    if (res.empty())
        res.push_back(stoi(input));
    memo[input] = res;
    return res;
}
    };

Also we could use Dynamic programming to solve the problem:
Bottom-up solution.

 vector<int> diffWaysToCompute(string input) {
    vector<int> data;
    vector<char> ops;
    int num = 0;
    char op = ' ';
    istringstream ss(input + "+");
    while(ss >> num && ss >> op){
        data.push_back(num);
        ops.push_back(op);
    }
    const int size = data.size();
    vector< vector<vector<int> > > dp(size, vector<vector<int> >(size, vector<int>()));
    for (int i = 0; i < size; i += 1)
        for (int j = i; j >= 0; j -= 1){
            if(i == j) {dp[j][i].push_back(data[i]); continue;}
            for (int k = j; k < i; k += 1){
                for (auto left : dp[j][k])
                    for (auto right : dp[k+1][i]){
                        int val = 0;
                       switch(ops[k]){
                       case '+': val = left + right; break;
                       case '-': val = left - right; break;
                       case '*': val = left * right; break;
                        }
                         dp[j][i].push_back(val);
                    }
            }

        }
        return dp[0][size-1];
   }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值