📜  不允许修改BST时BST中的第K个最大元素(1)

📅  最后修改于: 2023-12-03 15:21:30.685000             🧑  作者: Mango

不允许修改BST时BST中的第K个最大元素

二叉搜索树(Binary Search Tree,BST)是一种常见的数据结构,它是一个有序的二叉树,其中每个节点的值都大于其左子树中任意节点的值,小于其右子树中任意节点的值。在一个BST中,第K个最大元素是一种常见的需求,下面介绍三种解决方案。

解决方案一

第一种解决方案是使用递归方法。通过中序遍历BST,将元素按照从大到小的顺序排列。则第K个最大元素即为中序遍历序列的第K个元素。

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def kthLargest(self, root: TreeNode, k: int) -> int:
        self.result = None
        self.k = k
        self.helper(root)
        return self.result
    
    def helper(self, node):
        if node is None:
            return
        
        self.helper(node.right)
        self.k -= 1
        if self.k == 0:
            self.result = node.val
            return
        self.helper(node.left)
解决方案二

第二种解决方案是使用迭代方法,使用栈来模拟中序遍历BST的过程。通过将元素按照从大到小的顺序压入栈中,第K个最大元素即为栈中的第K个元素。

class Solution:
    def kthLargest(self, root: TreeNode, k: int) -> int:
        stack = []
        node = root
        while stack or node:
            while node:
                stack.append(node)
                node = node.right
            node = stack.pop()
            k -= 1
            if k == 0:
                return node.val
            node = node.left
解决方案三

第三种解决方案是使用Morris遍历,可以不用栈和递归来实现中序遍历。该算法使用线索树的思想,将每个节点的right指针指向它的后继,将每个节点的left指针指向它的前驱。具体过程可以查看这篇文章

class Solution:
    def kthLargest(self, root: TreeNode, k: int) -> int:
        node = root
        while node:
            if node.right is None:
                k -= 1
                if k == 0:
                    return node.val
                node = node.left
            else:
                pre = node.right
                while pre.left and pre.left != node:
                    pre = pre.left
                if pre.left is None:
                    pre.left = node
                    node = node.right
                else:
                    pre.left = None
                    k -= 1
                    if k == 0:
                        return node.val
                    node = node.left

以上三种解决方案中,第一种和第二种都需要O(n)的时间和空间复杂度,其中n为BST中节点的个数。第三种方法只需要O(h)的空间复杂度,其中h为BST的高度,但是最坏情况下时间复杂度仍然是O(n)。