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

112 阅读2分钟

题目描述

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

解题思路

算法,数据结构

栈,迭代,二叉搜索树的中序遍历

思路

对于这些数据结构,算法的作用,先做一个解释:

通过 迭代 来遍历所有的节点,这个过程中需要一个 来存储所有遍历到的左节点;

二叉搜索树的中序遍历结果是一个升序序列,可以据此找到最小 k

对于代码实现,首先是将 root 的所有左节点存储到 stack,其中 root 是整棵树的根节点,stack 是我声明的栈,是数组,这个过程通过 while 循环来做

放完所有左节点,会从栈中取出一个节点,它是当前的中间节点,让 k-- 做一次统计,然后对右节点做上述操作

以上过程是中序遍历的思路

所以只要当前节点存在或栈中节点还有剩余,就需要这个遍历的过程

过程

声明栈 stack 来存放所有左节点

最外层通过 while 循环来保证所有节点都遍历到,while 循环进行的条件是:

root || stack.length

因为 root 存在,我们需要放左节点。 stack 有节点存储,我们需要通过 pop 取出一个当前节点,做一次统计,递减 k,然后需要进行右节点的遍历

再次强调,这是二叉树中序遍历的实质!

然后在最外层 while 循环下,进行上述两个过程

root 存在

把所有的左节点放入 stack,这个过程仍然需要 while 循环

while (root) {
      stack.push(root)
      root = root.left
    }

这个 root 不需要单独设置一个变量来存储初始值,因为所有的节点我在改变的时候都放进栈了,在栈弹出的时候都可以拿到

stack.length 为 truthy

pop 一个元素作为当前节点,递减 k此时当 k === 0 时,当前节点就是要找的第 kroot 赋值为 root.right,继续遍历

代码

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} k
 * @return {number}
 */
var kthSmallest = function (root, k) {
    // use stack to store all of the left node
  const stack = []

  // keep storing when left node exist
  // pop a node when stack is not empty and root is null
  while (root || stack.length) {
    while (root) {
      stack.push(root)
      root = root.left
    }

    // after pop a node, which is the current mid node, decrement k
    // and when k is 0, return the current root.val
    root = stack.pop()
    k--
    if (!k) return root.val
    root = root.right
  }
}