2020.7.21 力扣每日

 

 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 == 0) {
19             return new ArrayList<TreeNode>();
20         }
21         return buildTree(1, n);
22     }
23     public List<TreeNode> buildTree(int start, int end) { 
24         List<TreeNode> res = new ArrayList<TreeNode>();
25         if (start > end){
26             res.add(null);
27             return res;
28         }
29         if (start == end){
30             res.add(new TreeNode(start));
31             return res;
32         }
33         for (int i = start; i <= end; i++){
34             List<TreeNode> leftTree = buildTree(start, i - 1);
35             List<TreeNode> rightTree = buildTree(i + 1, end);
36             for (TreeNode left : leftTree){
37                 for (TreeNode right : rightTree){
38                     TreeNode root = new TreeNode(i);
39                     root.left = left;
40                     root.right = right;
41                     res.add(root);
42                 }
43             }
44         }
45         return res; 
46     } 
47 }

解题思路:

   该题与先前的7.15日的每日一题相似,两者都是不同的二叉搜索树,不同的是,先前只需返回总数,而该题需要返回所有的树,但解题思路是相似的,要解决根节点的情况就要解决左右子树的情况,这里同样可以使用动态规划来实现,但此处先用递归来实现,便于理解。根据二叉搜索树的性质,显然,i作为根节点时的左子树范围为[0,i - 1],右子树范围为[i+1,n],同样,其余子树的情况也可用该形式表示,不过其start与end并非0与n,需要根据父节点的传入参数决定。设计好递归参数后,我们便需设计递归函数内部。

注意点:

  • 首先对于递归函数的返回值,显然是一个List<TreeNode>数组,用于存储不同的子树的根节点。所以递归函数内先定义一个res,作为结果传出
  • 其次对于子树来说,其根节点的内容是会变化的,即定义一个参数i,遍历范围为[start,end],作为跟节点所有可能的情况。
  • 接着便使用递归求左右子树的情况,即定义新的leftTree,rightTree数组,来存储左右子树返回的结果
  • 最后利用两个for循环,遍历左右子树的所有情况,将其与root连接,再将root节点添加入res内继续向上返回即可。
  • 由于每两个不同的left,right子树将会是一个不同的子树,所以root的根节点创建需在两个for循环内部,即每次都使用new TreeNode(i),创建新的root节点。 

空间复杂度与时间复杂度的计算涉及到卡特兰数,自行查阅理解。

 

posted @ 2020-07-21 23:04  小小码农-安  阅读(189)  评论(0编辑  收藏  举报