题目描述
给定一个二叉搜索树的根节点 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 时,当前节点就是要找的第 k 小
将 root 赋值为 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
}
}