看到二叉树搜索,第一时间想到的肯定是深度与广度优先,那么找第K大节点,我们最先想到的传统解题思路,肯定是定义一个数组,然后进行中序遍历,将每一个值都塞入数组中,最后数组反转取k-1值。
那么延伸一下,中序遍历从小到大的顺序肯定是,那么我们是否可以使用逆中序的方式,就会先拿到最大值,那么这样就不需要遍历完整个树,这样效率不就提升了吗
传统解法
function kthLargest(root, k) {
const res = []
const mapNode = (cur)=>{
if(!cur) return
mapNode(cur.left)
res.push(cur.val)
mapNode(cur.right)
}
mapNode(root)
return res.reverse() [k-1]
}
逆中序
/**
* 这道题传统的做法是采用中序遍历,用数组存储二叉树的每一个节点,时间复杂度和空间复杂度都是:O(N)(N 为节点的数量)
* 可以利用二叉搜索树的性质(所有左子节点的值都小于当前根节点,所有右子节点的值都大于当前根节点。),对以上算法进行优化。
中序遍历是从小到大获取节点的值,并记录,因此需要遍历完整棵树。如果以相反,即 右 -> 根 -> 左 从大到小的顺序遍历获取,
就无需遍历完整棵树,并且可以使用一个单独的变量记录已遍历了的前 K 个最大值,代码如下
* 逆中序遍历
*/
function kthLargest(root, k) {
const res = []
let count = 0
let cur = root
while (cur || res.length) {
while (cur) {
res.push(cur)
cur = cur.right
}
const node = res.pop();
if (++count === k) return node.val
if (node.left) cur = node.left
}
return 0
}