241.为运算表达式设计优先级(分治算法)

241. 为运算表达式设计优先级

labuladong 题解思路
给你一个由数字和运算符组成的字符串 expression ,按不同优先级组合数字和运算符,计算并返回所有可能组合的结果。你可以 按任意顺序 返回答案。

生成的测试用例满足其对应输出值符合 32 位整数范围,不同结果的数量不超过 104 。

示例 1:

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

示例 2:

输入:expression = "2*3-4*5"
输出:[-34,-14,-10,-10,10]
解释:
(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

思路: 

可以参考归并排序中分治算法的思想,全体有序是由两两有序、自底向上归并而成的

912.排序数组(归并排序)_{(sunburst)}的博客-CSDN博客

本题中,对于1 + 2 * 3 - 4 * 5,只加一次括号的话,有以下四种方法:

1、(1) + (2 * 3 - 4 * 5)

2、(1 + 2) * (3 - 4 * 5)

3、(1 + 2 * 3) - (4 * 5)

4、(1 + 2 * 3 - 4) * (5)

1 + 2 * 3 可以有两种加括号的方式,分别是:

(1) + (2 * 3) = 7

(1 + 2) * (3) = 9

即 left = [9, 7]

而 4 * 5 只有一种加括号方式,就是  right  = [20]

故 (1 + 2 * 3) - (4 * 5) 有 2 X 1 种加括号方式

分别是:

9 - 20 = -11

7 - 20 = -13

vector<int> diffWaysToCompute("(1 + 2 * 3) - (4 * 5)") 
{
    vector<int> res;
    /****** 分 ******/
    vector<int> = diffWaysToCompute("1 + 2 * 3");
    vector<int> right = diffWaysToCompute("4 * 5");
    /****** 治 ******/
    for (int a : left)
        for (int b : right)
            res.push_back(a - b);

    return res;
}
class Solution {
public:
    //分治法(归并算法也利用了此思想)
    //函数定义:返回字符串s所有加括号后的结果
    unordered_map<string,vector<int>> memo; //备忘录
    vector<int> diffWaysToCompute(string s)
    {
        vector<int> res;
        if(memo.count(s))//遇到和之前相同的s,直接返回它对应的res
        {
            return memo[s];
        }
        for(int i=0;i<s.size();i++)
        {
            if(s[i]=='+'||s[i]=='-'||s[i]=='*')//以运算符为中心,将s分割成两个字符串,分别递归计算
            {
                vector<int> left=diffWaysToCompute(s.substr(0,i));
                vector<int> right=diffWaysToCompute(s.substr(i+1,s.size()));
                for(int a:left)//通过子问题的结果,合成原问题的结果
                {
                    for(int b:right)
                    {
                        if(s[i]=='+')
                            res.push_back(a+b);
                        if(s[i]=='-')
                            res.push_back(a-b);
                        if(s[i]=='*')
                            res.push_back(a*b);        
                    }
                }
            }
        }
        if(res.size()==0)//base case:s中没有运算符,只剩下一个数字
        {
            res.push_back(stoi(s));
        }
        memo[s]=res;//记录已经算出的s与对应的res
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值