LeetCode题解——分治算法

川长思鸟来 2023-06-08 05:59 128阅读 0赞

文章目录

      1. 为运算表达式设计优先级
      • 分治算法
      1. 不同的二叉搜索树 II

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

给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含 +, - 以及 * 。

  1. 示例 1:
  2. 输入: "2-1-1"
  3. 输出: [0, 2]
  4. 解释:
  5. ((2-1)-1) = 0
  6. (2-(1-1)) = 2
  7. 示例 2:
  8. 输入: "2*3-4*5"
  9. 输出: [-34, -14, -10, -10, 10]
  10. 解释:
  11. (2*(3-(4*5))) = -34
  12. ((2*3)-(4*5)) = -14
  13. ((2*(3-4))*5) = -10
  14. (2*((3-4)*5)) = -10
  15. (((2*3)-4)*5) = 10

分治算法

按运算符分成左右两部分,分别计算后,利用分隔符,合并。
举个例子:23-45
第一次按分割,左边2,右边3-45
左边没有运算符,则直接等于2;右边继续分割,左边3,右边45,再继续分割右边,运算45=20,将3-20=-17返回,再计算2*(-17)=34压入vector;
接下来从-号开始分割,依次下去,就求出所有可能。

  1. vector<int> partition(string input)
  2. {
  3. vector<int> ans;
  4. if(input.find('+')==string::npos && input.find('-')==string::npos && input.find('*')==string::npos) //input 不包含+ - *
  5. {
  6. ans.push_back(stoi(input));
  7. return ans;
  8. }
  9. for(int i = 0; i < input.length(); ++i)
  10. if(input[i] == '+' || input[i] == '-' || input[i] == '*')
  11. for(auto left : partition(input.substr(0, i)))
  12. for(auto right : partition(input.substr(i+1)))
  13. {
  14. if(input.at(i) == '+')
  15. ans.push_back(left + right);
  16. else if(input.at(i) == '-')
  17. ans.push_back(left - right);
  18. else if(input.at(i) == '*')
  19. ans.push_back(left * right);
  20. }
  21. return ans;
  22. }
  23. class Solution {
  24. public:
  25. vector<int> diffWaysToCompute(string input) {
  26. vector<int> v2 = partition(input);
  27. sort(v2.begin(), v2.end());
  28. return v2;
  29. }
  30. };

95. 不同的二叉搜索树 II

给定一个整数 n,生成所有由 1 … n 为节点所组成的二叉搜索树。

示例:

  1. 输入: 3
  2. 输出:
  3. [
  4. [1,null,3,2],
  5. [3,2,null,1],
  6. [3,1,null,null,2],
  7. [2,1,3],
  8. [1,null,2,null,3]
  9. ]
  10. 解释:
  11. 以上的输出对应以下 5 种不同结构的二叉搜索树:
  12. 1 3 3 2 1
  13. \ / / / \ \
  14. 3 2 1 1 3 2
  15. / / \ \
  16. 2 1 2 3

首先来计数需要构建的二叉树数量。可能的二叉搜素数数量是一个 卡特兰数。
n个节点可以组成f(n)个二叉搜索树
format_png
我们从序列 1 …n 中取出数字 i,作为当前树的树根。于是,剩余 i - 1 个元素可用于左子树,n - i 个元素用于右子树。
如 前文所述,这样会产生 G(i - 1) 种左子树 和 G(n - i) 种右子树,其中 G 是卡特兰数。

现在,我们对序列 1 … i - 1 重复上述过程,以构建所有的左子树;然后对 i + 1 … n 重复,以构建所有的右子树。

这样,我们就有了树根 i 和可能的左子树、右子树的列表。

最后一步,对两个列表循环,将左子树和右子树连接在根上。

  1. class Solution {
  2. public:
  3. vector<TreeNode*> all_trees(int start, int end)
  4. {
  5. vector<TreeNode*> ans;
  6. if(start > end)
  7. {
  8. ans.push_back(nullptr);
  9. return ans;
  10. }
  11. for(int i = start; i <= end; ++i)
  12. {
  13. vector<TreeNode*> left = all_trees(start, i-1);
  14. vector<TreeNode*> right = all_trees(i+1, end);
  15. for(auto l : left)
  16. for(auto r : right)
  17. {
  18. TreeNode* root = new TreeNode(i);
  19. root->left = l;
  20. root->right = r;
  21. ans.push_back(root);
  22. }
  23. }
  24. return ans;
  25. }
  26. vector<TreeNode*> generateTrees(int n) {
  27. vector<TreeNode*> ans;
  28. if(n == 0)
  29. return ans;
  30. else
  31. ans = all_trees(1, n);
  32. return ans;
  33. }
  34. };

发表评论

表情:
评论列表 (有 0 条评论,128人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Leetcode 题解 - 分治算法

    其实,回溯、分治和动态规划算法可以划为一类,因为它们都会涉及递归。 回溯算法就一种简单粗暴的算法技巧,说白了就是一个暴力穷举算法,比如让你用回溯算法求子集、全排列、组合,你就