Leetcode230. Kth Smallest Element in a BST,二叉搜索树中第K小的元素

Leetcode230. Kth Smallest Element in a BST,二叉搜索树中第K小的元素

题目

题目链接
这道题有官方题解,就直接翻译过来了
感言:递归好写,但复杂度比不上迭代,迭代复杂度小,但经验不足的不太容易一下子写出来

树的遍历

树遍历有两种通用方法:

  • 深度优先遍历,Depth First Search (DFS)

从根开始访问,沿着一条分支直达叶子节点,再回到root,访问另一条分支.

DFS可以进一步划分为前序,中序和后序遍历,这里前中后指的是root相对于左右孩子的访问顺序.

  • 广度优先遍历,Breadth First Search (BFS)

从顶向下,逐层访问节点

下面的图片中,节点上的数字表示访问顺序,四个图分别表示DFS的前中后序遍历,以及BFS的遍历顺序

截图来自leetcode官方题解

方案

可以看到,对BST的中序遍历,输出结果就是升序排列的列表,遍历到第K个即是第K小元素

方法1,递归实现中序遍历

第k-1个元素就是答案

官方答案有java版,这里只摘抄了Python版:

class Solution:
    def kthSmallest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        def inorder(r):
            return inorder(r.left) + [r.val] + inorder(r.right) if r else []
    
        return inorder(root)[k - 1]

复杂度分析

时间复杂度,每个节点都访问一遍, O ( N ) \mathcal{O}(N) O(N)
空间复杂度,每个节点都进行了保存, O ( N ) \mathcal{O}(N) O(N)

方法2,迭代实现中序遍历

借助数据结构:栈,可以将上面的递归转为迭代.
迭代方案下,不需要遍历整颗树,可以在找到第K个元素后停止.

class Solution:
    def kthSmallest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        stack = []
        
        while True:
            while root:
                stack.append(root)
                root = root.left
            root = stack.pop()
            k -= 1
            if not k:
                return root.val
            root = root.right

复杂度分析

  • 时间复杂度, O ( H + k ) \mathcal{O}(H + k) O(H+k)
    H是树高,要先访问到叶子节点(H)才能开始弹出(k)
    最好情况,平衡树 O ( log ⁡ N + k ) \mathcal{O}(\log N + k) O(logN+k),最坏情况,所有节点都只有左节点的歪斜树 O ( N + k ) \mathcal{O}(N + k) O(N+k)

  • 空间复杂度,每个节点都进行了保存, O ( H ) \mathcal{O}(H) O(H)
    H是树高,最坏情况,歪斜的树,只有一个分支, O ( N ) \mathcal{O}(N) O(N) ,平衡树 O ( log ⁡ N ) \mathcal{O}(\log N) O(logN)

猜你喜欢

转载自blog.csdn.net/qq_17065591/article/details/115427358