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)