Top 100 Linked Question 修炼------第94题、第96题

本文详细讲解了LeetCode上的第94题(二叉树的中序遍历)和第96题(独特的二叉搜索树)。对于94题,提供了递归和非递归的解决方案。对于96题,介绍了使用卡特兰数和动态规划的方法。每种方法都伴随着详细的思路分析和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

94. Binary Tree Inorder Traversal

题目链接

题目解释:给定一颗二叉树,求其中序遍历的结果

Example:

Input: [1,null,2,3]
   1
    \
     2
    /
   3

Output: [1,3,2]

这一题对于我们来说可以说是非常简单的了,但是为什么还要写出来呢?当然是面试的时候问到了,请直接手撕代码,中序遍历非递归。嗯,开始吧:

题目分析:我们首先是求二叉树中序遍历的时候,为了表示我们的诚意(实际是为了避免我们的尴尬),那么还是直接手写一个递归的吧:

class Solution:
    def inorderTraversal(self, root: TreeNode):
        """
        采用递归的方式去解决
        :param root:
        :return:
        """
        res=[]
        def inorder(root,res):
            if root:
                inorder(root.left,res)
                res.append(root.val)
                inorder(root.right,res)
        inorder(root,res)
        return res

好了好了,基本的代码已经写出来了,那么采用非递归应该怎么写呢?递归和非递归之间仅仅是相差一个栈,那么可以采用一个栈,然后再进行相关的操作,下面直接给出非递归遍历的代码(记得手撕一遍.....):

    def inorderTraversal_iterable(self, root: TreeNode):
        """
        采用非递归的方式来解决
        :param root:
        :return:
        """
        if not root:
            return []
        stack =[]
        output = []
        while stack or root:
            if root:
                stack.append(root)
                root = root.left
            else:
                node = stack.pop()
                output.append(node.val)
                root = node.right
        return output

嗯,很重要,自己再次手撕了一遍.....

96. Unique Binary Search Trees

题目链接

题目解释:给定一个数字n,组成一个list=[1,2,....n],判断这个list可以组成多少个不同的二叉排序树

Example:

Input: 3
Output: 5
Explanation:
Given n = 3, there are a total of 5 unique BST's:

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3

题目分析:我觉得很熟悉的一道题,想当初在考研的时候,直接就是手写出答案,那个速度叫一个快呀(好吧,不吹牛皮了.....),至少写出两种方式吧,一种是前人已经总结好的内容,另外一种是根据二叉排序树的特点来做题

方法1:卡特兰数

根据前人总结的内容来解题,那么就直接给出卡特兰数得到计算公式啦:

catalan=\frac{1}{1+n}C_n^r

接下来就是直接计算就可以了:

    def numTrees(self, n):
        # 采用卡特兰数解决
        return math.factorial(2 * n) / (math.factorial(n) * math.factorial(n + 1))

方法2:动态规划

首先我们可以分析一下,什么是二叉排序树:它或者是一棵空树,或者是具有下列性质的二叉树:

(1)若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 

(2)它的左、右子树也分别为二叉排序树。

若F(n)表示[1...n]能够构成的不同BST的数量,那么:

        1、特殊情况,如果结点数为0,即n=0,为空树,F(0)=1;

        2、如果结点数为1,即n=1,F(1)=1;

        3、如果结点数为2,即n=2,F(2)=2;

        4、对于n>=2的情况,事实上,1,2,..n都可以作为根节点,若i作为根节点,根据BST的性质,左子树不为空时(左子树为空,只能是i=1),左子树的所有节点必须小于根节点,即[1,i-1]必须位于左子树,同时,右子数节点必须值必须大于根节点值,则[i+1,n]必须位于右子树;

         5、如上分析,对于[1,n],n>=2的情况,既然[1,n]每一个值都可以作为根节点,那我们需要遍历所有情况,时间复杂度为O(n),对于任何一种情况:根节点为i,则[1,i-1]为左子树,[i+1,n]为右子树,左子树有能够构成不同的BST的数量为:F(i-1),右子树能够构成的不同BST的数量为F(n-i);

             左右植树相互独立,那么:F(n)=F(i-1)*F(n-i),i属于[1,n],i有n种情况,须完全遍历
 

    def numTrees1(self, n):
        """
        :param n:
        :return:
        """
        # (n+1)个开销单元,res最终是某个节点的情况数
        res = [0] * (n + 1)
        res[0] = 1
        for i in range(1, n + 1):
            # 后面需要做range运算主要是因为构成二叉树的结点情况不同导致
            for j in range(i):
                res[i] += res[j] * res[i - 1 - j]
        return res[n]

总结

天气很美好呀,但是春天来了,很困.......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值