230. 二叉搜索树中第 K 小的元素 - 力扣(LeetCode)

题目:

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

示例 1:

img

输入:root = [3,1,4,null,2], k = 1
输出:1

示例 2:

img

输入:root = [5,3,6,2,4,null,null,1], k = 3
输出:3

提示:

  • 树中的节点数为 n
  • 1 <= k <= n <= 104
  • 0 <= Node.val <= 104

思路如下:

​ 这道题通过定义一个深度优先搜索函数,用于中序遍历。中序遍历二叉搜索树会得到一个递增的有序序列,从而利用递归的方式找到第 k 小的元素。


题解如下:

class Solution:
    def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:   
        # 定义一个嵌套的深度优先搜索(DFS)函数,用于中序遍历
        def dfs(node: Optional[TreeNode]) -> None:
            # 如果当前节点为空,直接返回
            if node is None:
                return
            
            # 递归遍历左子树
            dfs(node.left)
            
            # 声明 k 和 ans 是外层函数的变量,允许在内层函数中修改它们
            nonlocal k, ans
            
            # 每访问一个节点,将 k 减 1
            k -= 1
            
            # 如果 k 减到 0,说明当前节点的值就是第 k 小的元素
            if k == 0:
                ans = node.val
            
            # 递归遍历右子树
            dfs(node.right)


        # 初始化结果变量 ans,用于存储第 k 小的元素
        ans = 0
        # 调用 DFS 函数开始遍历
        dfs(root)
        
        # 返回结果
        return ans
    

题解示例:

二叉搜索树:
        3
       / \
      1   4
       \
        2

初始化
ans = 0
k = 1
定义 dfs 函数。
调用 dfs(root)
从根节点 3 开始。

遍历左子树
递归调用 dfs(1)。
继续遍历左子树,1 的左子节点为空,返回。
访问节点 1
k 减到 0,记录 ans = 1。

遍历右子树
递归调用 dfs(2) 和 dfs(4),但由于 k 已经为 0,直接返回。

返回结果
返回 ans = 1,即第 1 小的元素是 1。


逻辑梳理:

  1. 初始化结果变量
    • ans = 0:初始化一个变量 ans,用于存储找到的第 k 小的元素。
  2. 嵌套的 DFS 函数
    • def dfs(node: Optional[TreeNode]) -> None:定义一个递归函数 dfs,用于中序遍历二叉树。
  3. 递归终止条件
    • if node is None: return:如果当前节点为空,直接返回。
  4. 递归遍历左子树
    • dfs(node.left):递归调用 dfs 函数,遍历当前节点的左子树。
  5. 访问当前节点
    • nonlocal k, ans:声明 kans 是外层函数的变量,允许在内层函数中修改它们。
    • k -= 1:每次访问一个节点,将 k 减 1。
    • if k == 0: ans = node.val:如果 k 减到 0,说明当前节点的值就是第 k 小的元素,将其赋值给 ans
  6. 递归遍历右子树
    • dfs(node.right):递归调用 dfs 函数,遍历当前节点的右子树。
  7. 调用 DFS 函数
    • dfs(root):从根节点开始调用 dfs 函数,开始遍历。
  8. 返回结果
    • return ans:返回找到的第 k 小的元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值