python-leetcode 43.二叉搜索树中第K小的元素

题目:

给定一个二叉搜索树的根节点root,和一个整数k,请设计算法,查找其中第K小的元素(从1开始计数)

python-leetcode 43.二叉搜索树中第K小的元素_第1张图片

方法一:中序遍历

叉搜索树具有如下性质:

结点的左子树只包含小于当前结点的数。

结点的右子树只包含大于当前结点的数。

所有左子树和右子树自身必须也是二叉搜索树

二叉树的中序遍历即按照访问左子树——根结点——右子树的方式遍历二叉树;在访问其左子树和右子树时,我们也按照同样的方式遍历;直到遍历完整棵树。

因为二叉搜索树和中序遍历的性质,所以二叉搜索树的中序遍历是按照键增加的顺序进行的。于是,我们可以通过中序遍历找到第 k 个最小元素。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def kthSmallest(self, root, k):
        """
        :type root: Optional[TreeNode]
        :type k: int
        :rtype: int
        """
        stack=[]  #初始化一个空栈 stack,用于保存树的节点
        while root or stack: #有节点或者栈不为空的情况下继续遍历
            while root: #内部循环,遍历当前节点的左子树,一直将左子节点压入栈中,直到当前节点没有左子节点为止
                stack.append(root)  #将当前节点压入栈中
                root=root.left
            root=stack.pop() #从栈中弹出一个节点,即访问栈顶节点,栈顶节点是当前子树的最左边节点
            k-=1 #每访问一个节点,k 减 1
            if k==0:  #如果 k 为 0,说明当前节点就是我们要找的第 k 小节点,返回它的值
                return root.val
            root=root.right  #向右子树移动,继续遍历右子树

时间复杂度:O(H+k),H 是树的高度。在开始遍历之前,我们需要 O(H) 到达叶结点.当树是平衡树时,时间复杂度取得最小值 O(logN+k);当树是线性树(树中每个结点都只有一个子结点或没有子结点)时,时间复杂度取得最大值 O(N+k)。

空间复杂度:O(H)栈中最多需要存储 H 个元素。当树是平衡树时,空间复杂度取得最小值 O(logN);当树是线性树时,空间复杂度取得最大值 O(N)


方法二:记录子树的结点数

可以记录下以每个结点为根结点的子树的结点数,并在查找第 k 小的值时,使用如下方法搜索:

1.令node等于根结点,开始搜索

2.对当前结点node进行如下操作:

如果 node 的左子树的结点数 left 小于 k−1,则第 k 小的元素一定在 node 的右子树中,令 node 等于其的右子结点,k 等于 k−left−1,并继续搜索;

如果 node 的左子树的结点数 left 等于 k−1,则第 k 小的元素即为 node ,结束搜索并返回 node 即可

如果 node 的左子树的结点数 left 大于 k−1,则第 k 小的元素一定在 node 的左子树中,令 node 等于其左子结点,并继续搜索

class MyBst:
    def __init__(self,root):
        self.root=root
#统计以每个结点为根结点的子树的结点数,并存储在哈希表中
        self._node_num={}
        self._count_node_num(root)
    def kth_smallest(self,k):
        #返回二叉搜索树中第k小的元素
        node=self.root
        while node:
            left=self.get_node_num(node.left)  #获取当前节点左子树的节点数
            if left

时间复杂度:预处理的时间复杂度为 O(N),其中 N 是树中结点的总数;我们需要遍历树中所有结点来统计以每个结点为根结点的子树的结

点数。搜索的时间复杂度为 O(H),其中 H 是树的高度;当树是平衡树时,时间复杂度取得最小值 O(logN);当树是线性树时,时间复杂度取得最大值 O(N)。

空间复杂度:O(N)用于存储以每个结点为根结点的子树的结点数

源自力扣官方题解
 

你可能感兴趣的:(leetcode,算法,职场和发展)