从二叉树开始刷起(三)—— 二叉搜索树一个很重要的性质

本文探讨了二叉搜索树(BST)的特性,特别是中序遍历得到有序序列的性质。通过示例代码展示了寻找BST中第K小元素的不同方法,包括迭代和递归实现,强调了效率和复杂度的优化。此外,还介绍了如何将BST转换为累加树,通过反向遍历更新节点值,保持BST特性的同时实现累加功能。
摘要由CSDN通过智能技术生成

首先我觉得我们有必要了解一些二叉搜索树的基本特征,可以参考

数据结构(二):二叉搜索树(Binary Search Tree)

其中还有一个很重要的特征我们需要单独放在这提醒自己:BST 的中序遍历结果是有序的(升序)

我们先来看一道常规题目:

230. 二叉搜索树中第K小的元素

image-20211011160456054

利用上面的性质,我们很容易就想到直接构造中序遍历结果如何返回第K大的元素:

class Solution:
    def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
        res = []
        def inorder(root):
            if not root:return
            inorder(root.left)
            res.append(root.val)
            inorder(root.right)
        inorder(root)
        return res[k-1]

这样的话每一个元素都需要被遍历一遍,时间和空间复杂度都是O(N),虽然解决了问题,但终归不是一个最优解。

我们用迭代的方法尝试一遍呢?

class Solution:
    def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
        # 如果用迭代来做呢,比较难理解
        stack = []
        print(root)
        while True:
            # 找到左下侧那个没有左子树的节点
            while root:
                stack.append(root)
                root = root.left
            root = stack.pop()
            # root看当前节点是不是要找的节点,如果是的话,返回根节点,如果不是,再看一下右子树
            k -= 1
            if not k:
                return root.val
            root = root.right

这样的方法不太好理解,而且复杂度是O(H+k),所以还是不够好。有一种比较好的解决方案是,记录每个节点元素是第m大,然后比较k和m的大小,利用左子树小于根节点小于右子树的特性。可以将复杂度降到log(N),但是这样需要维护【每个节点以自己为根的这棵二叉树有多少个节点】这个值。那么针对递归的方法,我们能不能让它不要遍历所有节点就找到我们要的值从而适当减少复杂度呢。答案是可以的。

class Solution:
    def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:

        res = []
        def inorder(root):
            if not root:return
            inorder(root.left)
            if len(res)==k:return
            res.append(root.val)
            inorder(root.right)

        inorder(root)
        return res[-1]

当然也可以不用额外数组,仅用变量来保存最后的结果

class Solution:
    def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
        self.cnt = 0
        self.res = None
        def inorder(root):
            if not root:return
            inorder(root.left)
            if self.cnt==k:return 
            self.res = root.val
            self.cnt+=1
            inorder(root.right)

        inorder(root)
        return self.res

咱来继续:

538. 把二叉搜索树转换为累加树

或者:1038. 把二叉搜索树转换为累加树

image-20211013093013952

image-20211013093055029

这一题的思路主要是这样的:对于二叉树的题而言,我们经常考虑的是对某一个节点要做什么操作,而在本题中我们很难从这方面下手,但是利用BST的特性,我们就能很好的知道:可以从大到小降序打印 BST 节点的值,如果维护一个外部累加变量sum,然后把sum赋值给 BST 中的每一个节点,不就将 BST 转化成累加树了吗

于是我们尝试写一下代码,注意我们需要的是降序的结果,所以需要改变递归顺序。

class Solution:
    def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        self.sum = 0
        def traverse(root):
            if not root:return
            traverse(root.right)
            self.sum += root.val
            root.val = self.sum
            traverse(root.left)

        traverse(root)
        return root
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值