LeetCode日记——【算法】分治专题
预备知识:什么是分治
分治,字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。在计算机科学中,分治法就是运用分治思想的一种很重要的算法。分治法是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)等等。
题1:给表达式加括号
难度:Medium
题目描述:
给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含 +, - 以及 * 。
示例 1:
输入: "2-1-1"
输出: [0, 2]
解释:
((2-1)-1) = 0
(2-(1-1)) = 2
示例 2:
输入: "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 class Solution { 2 public List<Integer> diffWaysToCompute(String input) { 3 List<Integer> ways = new ArrayList<>(); 4 //对于字符串的每一个字符按顺序遍历 5 for(int i=0;i<input.length();i++){ 6 //取出当前字符存为c 7 char c=input.charAt(i); 8 //若当前字符为运算符 9 if(c=='+' || c=='-' || c=='*'){ 10 List<Integer> left = diffWaysToCompute(input.substring(0,i)); 11 List<Integer> right = diffWaysToCompute(input.substring(i+1)); 12 for(int l:left){ 13 for(int r:right){ 14 switch(c){ 15 case '+': 16 ways.add(l+r); 17 break; 18 case '-': 19 ways.add(l-r); 20 break; 21 case '*': 22 ways.add(l*r); 23 break; 24 } 25 } 26 } 27 } 28 } 29 if(ways.size()==0){ 30 ways.add(Integer.valueOf(input)); 31 } 32 return ways; 33 } 34 }
分析:
按顺序遍历每个字符,若遍历到运算符,就将表达式递归地分成两部分,当前字符的左边部分与当前字符的右边部分(均不包含当前字符)。然后做相应的运算。
题1:不同的二叉搜索树
难度:Medium
题目描述:
给定一个整数 n,生成所有由 1 ... n 为节点所组成的 二叉搜索树 。
示例:
输入:3
输出:
[
[1,null,3,2],
[3,2,null,1],
[3,1,null,null,2],
[2,1,3],
[1,null,2,null,3]
]
解释:
以上的输出对应以下 5 种不同结构的二叉搜索树:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
代码:
1 /** 2 * Definition for a binary tree node. 3 * public class TreeNode { 4 * int val; 5 * TreeNode left; 6 * TreeNode right; 7 * TreeNode() {} 8 * TreeNode(int val) { this.val = val; } 9 * TreeNode(int val, TreeNode left, TreeNode right) { 10 * this.val = val; 11 * this.left = left; 12 * this.right = right; 13 * } 14 * } 15 */ 16 class Solution { 17 public List<TreeNode> generateTrees(int n) { 18 if (n < 1) { 19 return new LinkedList<TreeNode>(); 20 } 21 return generateSubtrees(1, n); 22 } 23 24 private List<TreeNode> generateSubtrees(int s, int e) { 25 List<TreeNode> res = new LinkedList<TreeNode>(); 26 if (s > e) { 27 res.add(null); 28 return res; 29 } 30 for(int i=s;i<=e;++i){ 31 List<TreeNode> leftSubtrees = generateSubtrees(s, i - 1); 32 List<TreeNode> rightSubtrees = generateSubtrees(i + 1, e); 33 for (TreeNode left : leftSubtrees) { 34 for (TreeNode right : rightSubtrees) { 35 TreeNode root = new TreeNode(i); 36 root.left = left; 37 root.right = right; 38 res.add(root); 39 } 40 } 41 } 42 return res; 43 } 44 }
分析:
对1~n中每一个元素进行遍历。将元素组递归地分为左右两部分(不包括当前元素)。创建当前元素代表的当前根节点,然后分别将左边部分作为左子节点,右边部分作为右子节点。
分治专题完结撒花~