【路飞】完全二叉树的节点个数&&二叉搜素树的第k个节点

195 阅读2分钟

记录 2 道算法题

完全二叉树的节点个数

leetcode-cn.com/problems/co…


要求:

    * 完全二叉树是指只有倒数第二层的节点可能只有左节点或者没有节点,
    或者左右都有。倒数第二层以上的都是有左右节点。

比较直接的方法就是把节点都遍历一遍计个数就知道了。

    function countNodes(root) {
        let count = 0
        function f(root) {
          if (!root) return

          count++
          f(root.left)
          f(root.right)
        }

        f(root)
        return count
    }

优化一点的方法是 根据完全二叉树的特点,加上满二叉树的特点。只需要深度找最左边的节点和最右边的节点。如果数量相等,说明是个满二叉树,符合满二叉树就一定符合完全二叉树。

如果不相同的话就要往下一层设置根节点,画出一个个满二叉树。又是一个递归。

这样就不用遍历每一个节点就知道最后一层的情况,最差的情况还是要遍历全部。

    function countNodes(root) {
        let node = root
        let leftCount = 0
        while(node) {
            node = node.root
            leftCount++
        }
        
        node = root
        let rightCount = 0
        while(node) {
            node = node.right
            rightCount++
        }
        
        if (leftCount === rightCount) {
            // 算三角形阵内元素的个数的公式
            return Math.pow(2, leftCount) - 1
        }
        
        // 算上root自己 所以 +1
        // 递归 传入 新的根节点
        // 每次递归的主角就是根节点
        return 1 + countNodes(root.left) + countNodes(root.right)
    }

二叉搜索树的第k个节点

剑指 Offer 54. 二叉搜索树的第k大节点 - 力扣(LeetCode) (leetcode-cn.com)


这题需要发现一个规律,二叉搜素树满足 左节点比根节点小,右节点比根节点大。然后中序遍历 [左][根][右],刚好得到一个升序的数组。

所以如果按照 [右] [根] [左] 的方式遍历,则得到一个降序的数组。第k个就是我们需要的数。

    function kthLargest(root, k) {
        let val
        function f(root) {
            if(!root) return
            // 先找最右边的
            f(root.right)
            // 关键是计算 --k 然后保存值的操作放在哪里
            // 找完最右边之后,会一层层返回出来,就是这个时候。最大的数已经确定了
            // 做个提前结束的判断
            if (k === 0) return
            // 第k个
            if (--k === 0) val = root.val
            // 传入 left 将 left 视为根节点,一进来也是走 right 先,所以操作放在right 返回之后是合理的。
            f(root.left)
        }
        
        f(root)
        return val
    }

结束