我是靠谱客的博主 大意金鱼,最近开发中收集的这篇文章主要介绍2020_11_24 每日一题 222. 完全二叉树的节点个数,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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

说明:

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

示例:

输入:

     1
    / 
  2   3
 /   /   
4  5 6

输出: 6

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/count-complete-tree-nodes

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

数节点个数完全可以用正常treewalk 代码超级简单而且O(n)的时间复杂度也不算慢:

class Solution {

    public int countNodes(TreeNode root) {
        if(root == null) {
            return 0;
        }
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}

不过这是个完全二叉树是可以优化的,自己没想出来看题解了。首先,叶节点的深度至多相差一,并且最深的一层节点是从左往右排开的。如果叶节点深度相同(即一直往左走的深度和一直往右走的深度相同),那么节点数应该为2h-1(h从1开始编号);如果深度不同,可以在叶节点上一层二分搜索出有子节点的边界,左边加上子节点,右边不加。
假设搜索一层深度是h,那该层应该有2h-1个节点。可以将0到2h-1-1的这么些数和这些节点一一对应。数同时也表示了从根节点怎么走能到达对应节点。从高位往低位,如果是0指往右走,是1指往左走,这样数+1,指向的节点也正好右移一个位置。有数找对应节点的代码如下:

TreeNode walk(TreeNode root, int mm, int height) {
    TreeNode t = root;
    for(int i = 0; i < height; ++i) {
        if((mm & (1 << (height - i - 1))) != 0) {
            t = t.right;
        } else {
            t = t.left;
        }
    }
    return t;
}

这样在0到2h-1-1中二分搜索出边界就好:

int l = 0, r = pow2 - 1;//二分搜索
while(l < r) {
    int mid = (l + r) / 2;
    t = walk(root, mid, rHeight - 1);            
    if(t.left == null) {
        r = mid - 1;
    } else if(t.right == null) {
        l = mid;
        r = mid;
    } else {
        l = mid + 1;
    }
}

对于边界,确定的是边界左边都有两个子节点,边界右边没有,对于边界需要稍微讨论一下:

if(t.left == null) {
    return 2 * l + pow2 * 2 - 1;
} else if(t.right == null) {
    return 2 * l + pow2 * 2;
} else {
    return 2 * l + pow2 * 2 + 1;
}

完整代码:

class Solution {

    TreeNode walk(TreeNode root, int mm, int height) {
        TreeNode t = root;
        for(int i = 0; i < height; ++i) {
            if((mm & (1 << (height - i - 1))) != 0) {
                t = t.right;
            } else {
                t = t.left;
            }
        }
        return t;
    }

    public int countNodes(TreeNode root) {
        if(root == null) {
            return 0;
        }

        int lHeight = 0, rHeight = 0;
        TreeNode t = root;
        int pow2 = 1;
        while(t != null) {
            t = t.left;
            ++lHeight;
            pow2 *= 2;
        }
        t = root;
        while(t != null) {
            t = t.right;
            ++rHeight;
        }
        if(lHeight == rHeight) {
            return pow2 - 1;
        }
        pow2 /= 4;
        int l = 0, r = pow2 - 1;//二分搜索
        while(l < r) {
            int mid = (l + r) / 2;
            t = walk(root, mid, rHeight - 1);            
            if(t.left == null) {
                r = mid - 1;
            } else if(t.right == null) {
                l = mid;
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        t = walk(root, l, rHeight - 1);

        if(t.left == null) {
            return 2 * l + pow2 * 2 - 1;
        } else if(t.right == null) {
            return 2 * l + pow2 * 2;
        } else {
            return 2 * l + pow2 * 2 + 1;
        }
    }
}

这样的事件复杂度是logn * logn,每次walk需要logn,二分搜索到边界需要walk lgn次

最后

以上就是大意金鱼为你收集整理的2020_11_24 每日一题 222. 完全二叉树的节点个数的全部内容,希望文章能够帮你解决2020_11_24 每日一题 222. 完全二叉树的节点个数所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部