概述
给出一个完全二叉树,求出该树的节点个数。
说明:
完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第
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. 完全二叉树的节点个数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复