• LeetCode 0241.为运算表达式设计优先级 - DFS


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

    力扣题目链接:https://leetcode.cn/problems/different-ways-to-add-parentheses/

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

     

    示例 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
    

     

    提示:

    • 1 <= expression.length <= 20
    • expression 由数字和算符 '+''-''*' 组成。
    • 输入表达式中的所有整数值在范围 [0, 99] 

    方法一:DFS

    这道题让人很容易想到递归。

    我们用函数dfs(string s, int l, int r)来计算字符串s[l, r)部分都能表示什么值。

    vector<int> dfs(string& s, int l, int r) {  // [l, r)
        vector<int> ans;
    
        // Code here
    
        return ans;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    因此我们只需要调用dfs(s, 0, s.size())即可。

    vector<int> diffWaysToCompute(string& expression) {
        return dfs(expression, 0, expression.size());
    }
    
    • 1
    • 2
    • 3

    那么接下来的问题就是dfs函数怎么写。

    其实也不难。

    • 如果字符串s[l, r)中没有出现运算符的话,递归结束,我们只需要返回唯一的值即可。(例如125)
      if (!hasOp) {  // 不存在运算符
          ans.push_back(atoi(s.substr(l, r - l).c_str()));
      }
      
      • 1
      • 2
      • 3
    • 否则,我们以所有的运算符为分界,分别求出运算符左边的所有可能的值、右边所有可能的值,然后一一对应做运算,就得到了新的值。
      if (s[i] == '+' || s[i] == '-' || s[i] == '*') {
          hasOp = true;
          vector<int> left = dfs(s, l, i);
          vector<int> right = dfs(s, i + 1, r);
              for (auto& a : left)
                  for (auto& b : right)
                      ans.push_back(a OP b);  // 其中OP为+、-或*
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

    同时,我们使用哈希表map记录一下已经求过的值即可。

    map<pair<int, int>, vector<int>> ma;
    
    vector<int> dfs(string& s, int l, int r) {
        if (ma.count({l ,r}))  // 已经计算过[l, r)的话就不需要再计算一遍
            return ma[{l, r}];
        
        // Code Here
    
        return ma[{l, r}] = ans;  // 这是第一次计算的话,返回结果前用顺便哈希表记录一下,避免下次重复计算
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 时间复杂度 O ( 2 n ) O(2^n) O(2n),其中 n n n是原字符串中包含的运算符的个数
    • 空间复杂度 O ( 2 n ) O(2^n) O(2n)

    具体复杂度这里暂不给出证明,但是肯定能过。

    AC代码

    C++

    class Solution {
    private:
        map<pair<int, int>, vector<int>> ma;
    
        vector<int> dfs(string& s, int l, int r) {  // [l, r)
            if (ma.count({l ,r}))
                return ma[{l, r}];
            vector<int> ans;
            bool hasOp = false;
            for (int i = l; i < r; i++) {
                if (s[i] == '+' || s[i] == '-' || s[i] == '*') {
                    hasOp = true;
                    vector<int> left = dfs(s, l, i);
                    vector<int> right = dfs(s, i + 1, r);
                    if (s[i] == '+')
                        for (auto& a : left)
                            for (auto& b : right)
                                ans.push_back(a + b);
                    else if (s[i] == '-')
                        for (auto& a : left)
                            for (auto& b : right)
                                ans.push_back(a - b);
                    else if (s[i] == '*')
                        for (auto& a : left)
                            for (auto& b : right)
                                ans.push_back(a * b);
                }
            }
            if (!hasOp) {
                ans.push_back(atoi(s.substr(l, r - l).c_str()));
            }
            return ma[{l, r}] = ans;
        }
    public:
        vector<int> diffWaysToCompute(string& expression) {
            return dfs(expression, 0, expression.size());
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    同步发文于CSDN,原创不易,转载请附上原文链接哦~
    Tisfy:https://letmefly.blog.csdn.net/article/details/125555659

  • 相关阅读:
    注解(Annotation)基础
    计算机网络:奈氏准则与香农定理
    Interactive Tools Recommendation System integrating QT/ROS /Pytorch
    3、Bean的生命周期
    软考整体管理思维导图
    Unity下tga和png格式图片打包成AB包大小和加载速度测试
    球谐函数实现环境光照漫反射实践
    Iphone自动化指令每隔固定天数打开闹钟关闭闹钟(二)
    一句话概括C#7.3+以后版本的??(俩问号)和??=(俩问号一个等于)的含义
    超实用 :大部分的人都不知道的一个Python技巧
  • 原文地址:https://blog.csdn.net/Tisfy/article/details/125555659