python - 这种递归二分搜索是如何工作的?用于查找 bst 中的第 k 个最小节点
问题描述
前几天我看到了这个二分搜索/dps 解决方案,我很难理解它是如何工作的。
def kthSmallest(self, root, k): # Binary Search - DPS
def countNodes(node):
if not node:
return 0
return 1 + countNodes(node.left) + countNodes(node.right)
count = countNodes(root.left)
if k <= count:
return self.kthSmallest(root.left, k)
elif k > count + 1:
return self.kthSmallest(root.right, k - 1 - count)
return root.val
解决方案
我们先来看看countNodes
里面定义的函数kthSmallest
:它root
通过递归聚合以 和 为根的BST的节点数来计算以 为根的BST的节node.left
点数node.right
。基本情况是没有节点,在这种情况下countNodes
返回 0。
背后的逻辑kthSmallest
取决于 BST 的属性,即给定节点的键大于以左孩子为根的子树中的所有节点,并且小于以右孩子为根的子树中的所有节点。在整个递归调用中保持不变的是,第 k 个最小节点包含在以 为根的子树中root
: 在第一次调用时,root
是 BST 的根,所以这个条件成立。然后该算法计算 的左子树中的节点数root
。根据 BST 属性,这是小于 的节点数root
。如果这个数大于或等于k
,则第 k 个最小的节点必须在左子树中,因此算法递归到左子树。如果数字 + 1 小于k
,寻找的节点必须在右子树中,因此算法在那里递归(添加+1,因为节点本身被计算在内)。此递归需要调整k
为,k-1-count
因为count + 1
节点数小于 的右子节点root
。最后,如果k=count + 1
当前node
是第 k 个最小的节点(因为它的左子树有k-1
节点)并且算法返回节点的值。
这是一个示例:假设我们有以下 BST,并且正在寻找第三个最小的节点:
3.
/ \
1 5
/\ / \
4 6
/\ /\
8
/\
我们首先调用kthSmallest
根 (3),count
1 也是如此,因为k = 3 > count + 1
,算法递归到具有新调整的右子树k=3-1-1=1
:
5
/ \
4 6
/\ /\
8
现在count
是 1 并且因为k=1 <= 1
,算法递归到左子树:
4
/\
现在count
是 0 所以k = count + 1
算法返回4
,它是序列中第三小的节点1 3 4 5 6 8
。
推荐阅读
- ruby-on-rails - ActiveRecord::ConnectionAdapters::OracleEnhancedConnectionException "DESC 表名,它存在吗?" 为测试设置运行迁移时出错
- c# - 在 c# 应用程序中使用 python 的最佳实践是什么?
- python - 递归 Python 函数严重影响 Django 站点性能
- c - 如何根据条件将一个数组中的元素添加到另一个未定义大小的数组中?
- java - JSch 库 Kerberos 支持
- ios - iOS:如何在我的应用程序中更改 alertView 的每个文本、标题、按钮的每种字体?
- vb.net - 如何从 Dbnull 类型转换为 Date 类型
- angular - 如何在Angular 6中的Ngx-bootstrap模态中将组件作为模态体传递
- java - JComboBox 并不总是将值保存到 TableModel
- java - 在 Java 中使用 Javamail 获取消息内容类型时出错