力扣-二叉搜索树的第K大节点

129 阅读1分钟

看到二叉树搜索,第一时间想到的肯定是深度与广度优先,那么找第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
}