leetcode241为运算表达式设计优先级——分治

题目链接如下为运算表达式设计优先级

给你一个由数字和运算符组成的字符串 expression ,按不同优先级组合数字和运算符,计算并返回所有可能组合的结果。你可以 按任意顺序 返回答案。
生成的测试用例满足其对应输出值符合 32 位整数范围,不同结果的数量不超过 104 。

下面是测试样例

输入:expression = "2-1-1"
输出:[0,2]
解释:
((2-1)-1) = 0 
(2-(1-1)) = 2

错误思路:写这道题的第一反应是看到数据长度为20,一想那直接dfs就好了,在dfs的时候把按照符号栈弹出和不弹出两种情况。但是存在一个问题在符号栈弹出的时候,是否需要递归的对之前的符号栈进行弹出,如果不弹出,则会漏掉一些情况。
那么应该怎么做呢?
这道题的思路其实是采用分治的思路,看作两段表达式通过符号合并。就可以拆成三种情况 e x p r e s s i o n 1 + e x p r e s s i o n 2 expression1+expression2 expression1+expression2 e x p r e s s i o n 1 − e x p r e s s i o n 2 expression1-expression2 expression1expression2 e x p r e s s i o n 1 ∗ e x p r e s s i o n 2 expression1*expression2 expression1expression2。分别求 e x p r e s s i o n 1 expression1 expression1 e x p r e s s i o n 2 expression2 expression2的值再进行组合合并就行。
在中间 e x p r e s s i o n 1 expression1 expression1 e x p r e s s i o n 2 expression2 expression2的值可能会计算多次,因此可以用unordered_map去先存储中间值。

class Solution {
public:
    unordered_map<string, vector<int>> mp;
    vector<int> diffWaysToCompute(string expression) {
        int n = expression.size(); 
        return func(expression, 0, expression.size()-1);
    }
    int f(int val1, int val2, char op){
        if(op=='+') return val1 + val2;
        if(op=='-') return val1 - val2;
        if(op=='*') return val1 * val2;
        return 0;
    }
    vector<int> func(string expression, int from, int to){
        vector<int> ans;
        if(from>to) return {};
        if(from==to) return {expression[from]-'0'};
        if(from+1==to) return {(expression[from]-'0')*10+expression[to]-'0'};
        if(mp.find(expression.substr(from, to-from+1))!=mp.end()) return mp[expression.substr(from, to-from+1)];
        for(int i=from; i<=to; ++i){
            char c = expression[i];
            if(c=='+' || c=='*' || c=='-'){
                vector<int> ans1 = func(expression, from, i-1);
                vector<int> ans2 =func(expression, i+1, to);
                for(auto i:ans1){
                    for(auto j:ans2){
                        ans.push_back(f(i,j,c));
                    }
                }
            }
        }
        mp[expression.substr(from, to-from+1)] = ans;
        return ans;
    }
};

最后总结一下采用分治思路的题目有什么特点:
大问题可以分成多个子问题解决,子问题通过一些操作可以合并成大问题
这里就是将大表达式看作了多个小表达式求和/差/乘积

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值