2025/8/9
题目:

我的思路:
我们之前已经知道了二叉搜索树的中序遍历访问的数字是升序的。而这里要我们求出第K小的元素值。而我们一开始又不知道这颗树有几个节点,因此没办法很快地通过二分查找的方式去得到。所以只能先按中序遍历的方式,去遍历到第K个元素即可
①用递归的方式去中序遍历
②每次访问到一个元素的时候让k = k-1
③如果k == 0,则说明这个就是目标元素,直接返回即可
④如果发现已经得到了结果值,那就不必再中序遍历右子树
具体代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
#中序遍历查找
self.res = -1
self.k = k
def midVisit(root:Optional[TreeNode]) -> int:
if not root:
return -1
#查找左子树
midVisit(root.left)
#访问根节点
self.k -= 1
if self.k == 0:
self.res = root.val
#访问右子树(如果还没有找到结果的话)
if self.res == -1:
midVisit(root.right)
midVisit(root)
return self.res
时间复杂度:O(N)
空间复杂度:O(N)
优化思路:
1.二叉搜索树
如果我们需要更加频繁地去查找第K个元素,上述这种方法就会不那么方便。而我们之所以上面要这样逐个遍历每个节点主要是因为我们不知道这个树的节点数。因此,我们可以先对这颗树进行预处理,记录它每个节点作为根节点的子树的节点数。
比如这个值为4的节点作为根节点的子树的节点数是3
对于这些节点对应的节点数,我们可以把它存在一个哈希表中以快速获取。
那我们的算法就可以改进成:
①获取当前节点的左子树的节点数left
②如果left == k-1 说明当前这个节点的值就是目标值
③如果left > k-1 说明目标值在左子树中;此时需要把节点指针往左子树移动
④如果left < k-1 说明目标值在右子树中;此时需要把节点指针往右子树移动,同时更新k的值(k = k - left - 1【因为已经排除了左子树和当前节点是目标值的可能】)
⑤一直循环步骤二三四直到返回了为止
其中对这颗树进行预处理主要是处理获得其哈希表:
①当前节点作为根节点的子树的节点数 = 1 + 其左子树节点数 + 其右子树节点数
可以看出来是可以进行递归计算处理的
具体代码如下:
#二叉搜索树
class MyBst:
def __init__(self, root:TreeNode):
#预处理这颗树,获取每个节点作为根节点的子树的节点树(哈希表存储)
self.root = root
self.node_num = {}
self.count_node_num(root)
def count_node_num(self, root:TreeNode) -> int:
#计算当前这颗树的节点数量
if not root:
return 0
self.node_num[root] = 1 + self.count_node_num(root.left) + self.count_node_num(root.right)
return self.node_num[root]
def get_node_num(self, root:TreeNode) -> int:
#获取这颗树的节点数
return self.node_num[root] if root else 0
def get_minKNum(self, k) -> int:
#获取当前这颗树第K小的节点值
node = self.root
while True:
left = self.get_node_num(node.left)
if left == k-1:
return node.val
elif left > k-1:
#说明值在左子树中
node = node.left
else:
#说明值在右子树中
node = node.right
k -= left+1 #更新k的值(减去左子树的节点数量+根节点)
def print_nodeNum(self):
#打印查看每个节点作为根节点的子树的节点数量
for k in self.node_num:
print(k.val, self.node_num[k])
class Solution:
def kthSmallest(self, root: TreeNode, k: int) -> int:
#实例化这个二叉搜索树
bst = MyBst(root)
#然后调用里面的方法
return bst.get_minKNum(k)
时间复杂度:O(N) 预处理 + O(H) 查询
空间复杂度:O(N)
这里也算是用到了面向对象的思想来处理解决
其他:
那如果这颗树会被频繁修改且需要频繁访问这个第K小的元素的时候又该怎么办呢?
这个问题我们用平衡二叉搜索树解决,但是这个看起来有点复杂,我还没有细看的。只知道它有这么个用处。具体去LeetCode中查看官方题解
总结:
①这里我们又用到了中序遍历是搜索二叉树的升序排序的结论来做题
②如果要频繁访问,那就要预处理这个搜索二叉树(知道每个节点作为根节点的子树的节点数)
③如果要对这颗树会进行增删改查的时候,那就需要用到平衡二叉搜索树
④Python中对字典的迭代器访问是访问其Key值
&spm=1001.2101.3001.5002&articleId=150111681&d=1&t=3&u=a835161219a64afa909303081142d723)
194

被折叠的 条评论
为什么被折叠?



