[LeetCode] 95. Unique Binary Search Trees II

45 篇文章 0 订阅
33 篇文章 0 订阅

原题链接:https://leetcode.com/problems/unique-binary-search-trees-ii/

1. 题目介绍

Given an integer n, generate all structurally unique BST’s (binary search trees) that store values 1 … n.
给出一个整数n,返回从1到n的所有数形成的不一样的二叉搜索树路径。
Example:

Input: 3
Output:
[
  [1,null,3,2],
  [3,2,null,1],
  [3,1,null,null,2],
  [2,1,3],
  [1,null,2,null,3]
]

在这里插入图片描述

2. 解题思路

这道题和 96. Unique Binary Search Trees 是同一道题,但是 96. Unique Binary Search Trees 只需要返回二叉树的个数,而本题则是返回二叉树本身。

动态规划法


注:本思路根据 https://blog.csdn.net/chilseasai/article/details/50083201 改写而来,感兴趣的读者可以直接去看原文。


解决本题可以使用动态规划的思路,将问题逐步分解。为了求出所有不同的二叉树,需要交替按照下面两步进行:
1 . 在一个范围内选取一个结点作为根。
2 . 每选取一个结点作为根,就把树切分成左右两个子树,直至该结点左右子树为空。

一开始,这个范围是(1,n),接下来如果选取 i 作为根节点,那么这个 i 的左子树的范围就是(1,i-1),左子树在(1,i-1)中再选一个节点作为根;右子树的范围就是(i+1,n),右子树在(i+1,n)中选一个节点作为右子树的根。依次细分下去

于是,这是一个可以划分成子问题求解的题目,所以可以使用动态规划求解。

但具体对于本题来说,采取的是自底向上的求解过程。
1 . 选出根结点后应该先分别求解该根的左右子树集合,也就是根的左子树有若干种,它们组成左子树集合,根的右子树有若干种,它们组成右子树集合。
2 . 然后将左右子树相互配对,每一个左子树都与所有右子树匹配,每一个右子树都与所有的左子树匹配。然后将两个子树插在根结点上。
3 . 最后,把根结点放入总的List结果中。

具体实现可以参考以下代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<TreeNode> generateTrees(int n) {
        if(n < 1){//测试样例中有一个n = 0
            return new ArrayList<>();
        }
        return helper(1,n);
    }
    public List<TreeNode> helper(int begin, int end){
        List<TreeNode> ans = new ArrayList<>();
        if(begin > end){
            ans.add(null);//添加null而不是直接返回,可以方便处理子树为空的情况
            return ans;
        }
        
        for(int i =begin ; i<=end ; i++){
        //确定根节点是i后,求所有左子树集合和右子树集合
            List<TreeNode> leftChild  = helper(begin, i-1);
            List<TreeNode> rightChild = helper( i+1 , end);
            
            //从取出集合中的左右子树一一配对
            for(int j = 0; j<leftChild.size();j++){
                for(int k = 0;k<rightChild.size();k++){
                    TreeNode root = new TreeNode(i);
                    root.left = leftChild.get(j);
                    root.right = rightChild.get(k);
                    ans.add(root);
                }
            }
        }
        return ans;
    }
}

3. 参考资料

https://blog.csdn.net/chilseasai/article/details/50083201

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值