分治策略(Divide and Conquer)

简介(Introduction)

分治策略(Divide and Conquer)是对于一个规模为 \(n\) 的问题,若该问题可以容易地解决(比如说规模 \(n\) 较小)则直接解决,否则将其分解\(k\) 个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。



描述(Description)

  • 在分治策略中,我们递归的求解一个问题,在每层递归中应用如下三个步骤
    1. 分解:将一个问题划分为若干个子问题,子问题的形式与原问题一样,不过规模更小。
    2. 解决:递归的求解出子问题。若子问题的规模非常小则停止递归,直接求解。
    3. 合并:将子问题的解合并成原问题的解


应用(Application)


  1. 二分搜索
  2. 大整数乘法
  3. \(Strassen\) 矩阵乘法
  4. 棋盘覆盖
  5. 归并排序
  6. 快速排序
  7. 线性时间选择
  8. 最接近点对问题
  9. 循环赛日程表
  10. 汉诺塔
  11. ...



为运算表达式设计优先级


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

生成的测试用例满足其对应输出值符合 32 位整数范围,不同结果的数量不超过 \(10^4\)

提示:

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

示例 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. 分解:按运算符分成左右两部分,分别求解
      2. 解决:实现一个递归函数,输入算式,返回算式解
      3. 合并:根据运算符合并左右两部分的解,得出最终解
  • 题解:

    // C++ Version
    
    class Solution {
    public:
        vector<int> diffWaysToCompute(string expression) {
            vector<int> res; //存放结果
            int len = expression.size();
            for(int i = 0; i < len; i++){
                char c = expression[i];
                if(c == '+' || c == '-' ||c == '*'){
                    //找到运算符,向左进行分割
                    auto left = diffWaysToCompute(expression.substr(0, i));
                    //向右进行分割
                    auto right = diffWaysToCompute(expression.substr(i + 1, len - i - 1));
    
                    for(int l : left){
                        for(int r : right){
                            if(c == '+'){
                                res.push_back(l + r);
                            }else if(c == '-'){
                                res.push_back(l - r);
                            }else if(c == '*'){
                                res.push_back(l * r);
                            }
                        }
                    }
                }
            }
            //如果res中没有数字,说明expression本身为一个数字
            if(res.size() == 0){
                res.push_back(stoi(expression));
            }
            return res;
        }
    };
    

posted @ 2023-06-12 11:20  FFex  阅读(8)  评论(0编辑  收藏  举报