【LeetCode】230. 二叉搜索树中第 K 小的元素

leetcode

 

解题思路

二叉搜索树(BST)的中序遍历结果是一个​​严格递增序列​​,利用这一特性:

  1. ​​中序遍历顺序​​:左子树 → 根节点 → 右子树
  2. ​​第 K 小元素​​:中序遍历的第 K 个节点即为所求
  3. ​​迭代优化​​:使用栈模拟中序遍历,找到第 K 个节点后立即终止遍历,避免全树遍历

区别于递归解法,迭代法空间复杂度更低(O(h)),且可提前终止

关键步骤

  1. ​​栈初始化​​:准备栈存储遍历路径
  2. ​​左子树入栈​​:从根节点开始,将所有左子节点入栈(保证最小节点在栈顶)
  3. ​​节点处理​​:
    • 弹出栈顶节点(当前最小节点)
    • k-- 并检查 k==0(找到第 K 小元素)
  4. ​​转向右子树​​:当前节点指向其右子节点,重复步骤2-3

代码实现

type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}

func kthSmallest(root *TreeNode, k int) int {
    stack := []*TreeNode{} // 初始化栈

    for len(stack) > 0 || root != nil {
        // 1. 左子树入栈(深度优先)
        for root != nil {
            stack = append(stack, root)
            root = root.Left
        }

        // 2. 弹出当前最小节点
        n := len(stack)
        node := stack[n-1]
        stack = stack[:n-1]

        // 3. 检查是否第K小
        k--
        if k == 0 {
            return node.Val // 找到目标
        }

        // 4. 转向右子树
        root = node.Right
    }
    return -1 // k超出范围
}

示例测试

func main() {
    // 示例1:root = [3,1,4,null,2], k=1 → 输出1
    root1 := &TreeNode{Val: 3}
    root1.Left = &TreeNode{Val: 1}
    root1.Right = &TreeNode{Val: 4}
    root1.Left.Right = &TreeNode{Val: 2}
    fmt.Println(kthSmallest(root1, 1)) // 1

    // 示例2:root = [5,3,6,2,4,null,null,1], k=3 → 输出3
    root2 := &TreeNode{Val: 5}
    root2.Left = &TreeNode{Val: 3}
    root2.Right = &TreeNode{Val: 6}
    root2.Left.Left = &TreeNode{Val: 2}
    root2.Left.Right = &TreeNode{Val: 4}
    root2.Left.Left.Left = &TreeNode{Val: 1}
    fmt.Println(kthSmallest(root2, 3)) // 3
}

复杂度分析

指标平衡树最坏情况(链表)说明
​​时间复杂度​​ O(H + k) O(n) H为树高,k为查找序号
​​空间复杂度​​ O(H) O(n) 栈深度最大为树高

​​H与k的关系​​:

  • 平衡树:H = log₂n,复杂度 ≈ O(log n + k)
  • 最坏情况:树退化为链表,H = n,复杂度 O(n)

🔍 关键点总结

  1. ​​BST特性利用​​:中序遍历有序性是核心依据
  2. ​​迭代优势​​:避免递归栈溢出,空间复杂度优化至O(h)
  3. ​​提前终止​​:找到第k个节点立即返回,减少无效遍历
  4. ​​边界处理​​:
    • 空树直接返回-1
    • k>节点数时返回-1(题目保证k有效可省略)
  5. ​​方向控制​​:左子树优先入栈保证升序访问
posted @ 2025-06-08 15:48  云隙之间  阅读(43)  评论(0)    收藏  举报