LeetCode 222. 完全二叉树的节点个数

目录结构

1.题目

2.题解

2.1递归计数

2.2二分查找+位运算


1.题目

给出一个完全二叉树,求出该树的节点个数。

说明:

完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^h个节点。

示例:

输入: 
    1
   / \
  2   3
 / \  /
4  5 6

输出: 6

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-complete-tree-nodes
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2.题解

2.1递归计数

public class Solution222 {

    @Test
    public void test222() {
        TreeNode root = new TreeNode(1, new TreeNode(2, new TreeNode(4), new TreeNode(5)),
                new TreeNode(3, new TreeNode(6), null));
        System.out.println(countNodes(root));
    }

    public int countNodes(TreeNode root) {
        if (root != null) {
            return countNodes(root.left) + countNodes(root.right) + 1;
        }
        return 0;
    }
}
  • 时间复杂度:O(n),每个节点遍历一次。
  • 空间复杂度:O(logn),题设给定为完全二叉树,故递归深度为树高度\left \lceil logn \right \rceil

2.2二分查找+位运算

根据题设,根节点为第0层,完全二叉树的最大层数为h。

由完全二叉树的性质:

  1. 最左边的节点一定位于最底层,故从根节点出发,不断访问左子树,直到遇到叶节点,该叶节点即为完全二叉树的最左边的节点,经过的路径长度即为最大层数h;
  2. 对于第i层(0\leq i< h),有2^i个节点;
  3. 对于第h层,包含的节点个数最少为1,最多为2^h
  4. h-1层包含节点个数2^{h}-1

故对于最大层数为 h的完全二叉树,节点个数一定在[2^h, 2^{h+1}-1]的范围内,可在该范围内通过二分查找的方式得到完全二叉树的节点个数:

  1. 通过上述性质1获取最大层数h;
  2. 根据h可由上述性质3得到第h层个数的区间[1, 2^h],将其由0开始编号,故编号范围是[0,2^h-1](原因见下面判断编号k是否存在);
  3. [0,2^h-1]中由二分查找法搜索存在的最大编号k(若节点k存在,则最底层节点个数一定≥k+1,若节点k不存在,则最底层节点个数一定<k+1);
  4. 最后返回2^h-1+k+1=2^h+k

判断编号k是否存在:

  • 若将父节点与左子节点之间的边用0表示,父节点与右子节点之间的边用1表示,则最底层节点的编号的二进制从高位到低位正好表示了根节点到该节点的路径,故可由此判断是否存在;
  • 这样正是将最底层从0编号的原因。
public class Solution222 {

    @Test
    public void test222() {
        TreeNode root = new TreeNode(1, new TreeNode(2, new TreeNode(4), new TreeNode(5)),
                new TreeNode(3, new TreeNode(6), null));
        System.out.println(countNodes(root));
    }

    public int countNodes(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int level = 0;
        TreeNode tmp = root;
        while (tmp.left != null) {
            level++;
            tmp = tmp.left;
        }
        int left = 0, right = (1 << level) - 1, bits = 1 << (level - 1);
        while (left < right) {
            int mid = (right - left + 1) / 2 + left;
            if (judge(root, bits, mid)) {
                left = mid;
            } else {
                right = mid - 1;
            }
        }
        return (int) (Math.pow(2, level)) + left;
    }

    public boolean judge(TreeNode root, int bits, int k) {
        while (root != null && bits > 0) {
            if ((bits & k) == 0) {
                root = root.left;
            } else {
                root = root.right;
            }
            bits >>= 1;
        }
        return root != null;
    }
}
  • 时间复杂度:O(log^2n)O(h)=O(logn)获取最大层数,对最底层h的节点[1, 2^h]进行二分查找O(log2^h)=O(h)次,且每个判断是否存在需要O(h)
  • 空间复杂度:O(1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值