如何计算完全二叉树的节点数 :: labuladong的算法小抄 #987
Replies: 26 comments 7 replies
-
牛啊牛啊,学到了! |
Beta Was this translation helpful? Give feedback.
-
或者这样, 容易理解一些: 完全二叉树节点总数是: // 每一层都是2的(i-1)次幂
int res = 0;
for (int i = 1; i <= lo;i++) {
res += Math.pow(2, i - 1);
}
return res; |
Beta Was this translation helpful? Give feedback.
-
算法的时间复杂度怎么算的呀, 每次递归的复杂度是while循环(logN), 最后return的那个递归只有一个会被执行,因此return的复杂度相当于递归内容的复杂度(while循环logN), 最后相乘? |
Beta Was this translation helpful? Give feedback.
-
递归的次数 x 每次递归的时间复杂度,递归次数就是树的高度 O(logN),每次递归所花费的时间就是 while 循环,需要 O(logN),所以总体的时间复杂度是 O(logN*logN)。 |
Beta Was this translation helpful? Give feedback.
-
dong哥的解释很详细 |
Beta Was this translation helpful? Give feedback.
-
代码注释有个小错误,代码中的lh和rh代表的并不是左右子树的高度,而是一直沿最左和最右走的长度,如果lh == rh, 则说明完全二叉树是满二叉树。 |
Beta Was this translation helpful? Give feedback.
-
@strickland0702 明白你的意思了,有道理,我改下表述 |
Beta Was this translation helpful? Give feedback.
-
看评论区没有说,我来说一下单纯计数的那一部分,没有返回0是怎么计算的,望斧正 按理说如果是单纯计数,到了null结点需要返回0,而东哥的代码并没有显式的返回0,其实已经囊括在
这部分中,若是只有左右子树中的一个,比如左子树只有一个,右子树为空, |
Beta Was this translation helpful? Give feedback.
-
乖乖,又长见识了 |
Beta Was this translation helpful? Give feedback.
-
我能理解你说的计算那部分full tree的计算,,但是另一半呢? 就是总有一条路径只有左孩子,没有右孩子的,不得还是一种naive的方式.我的理解是, 这条路径其实就是单独算, 复杂度是O(h) |
Beta Was this translation helpful? Give feedback.
-
东哥我没理解非满二叉树子树的递归复杂度计算。对于满二叉树的子树遍历中有两个while,按照层数从上到下高度为log(n)因此复杂度为O(logn)没毛病,非满二叉树的子树相当于需要遍历该子树中的每一个节点吧?感觉递归次数并不是树的高度而是子树中节点的数目,递归函数每次执行的复杂度为O(logn),节点数目准确来说应该是N / 2 (因为子树包含一半的节点), 因此复杂度不应该是O(logn * n / 2)嘛? |
Beta Was this translation helpful? Give feedback.
-
@lhcezx 你说的这句话不对。注意代码,非满二叉树也只需要从根节点走到叶子节点,即遍历「高度」而不是「所有节点」,所以所需时间就是 logN,因此结果就是 O(logN*logN)。 |
Beta Was this translation helpful? Give feedback.
-
check in |
Beta Was this translation helpful? Give feedback.
-
举例子算一下,如果6层树,最坏情况下
总计算量就是
|
Beta Was this translation helpful? Give feedback.
-
打卡 ”完全二叉树的左右两边,总有一个是满的“ 有趣 |
Beta Was this translation helpful? Give feedback.
-
go version func countNodes(root *TreeNode) int {
if root == nil {return 0}
l := 0
left := root
for left != nil {
left = left.Left
l++
}
r := 0
right := root
for right != nil {
right = right.Right
r++
}
if l == r {
return int(math.Pow(2, float64(l)) - 1)
}
return 1 + countNodes(root.Left) + countNodes(root.Right)
} |
Beta Was this translation helpful? Give feedback.
-
看了那么多回答,计算复杂度的结果我还是没看懂>_<|| |
Beta Was this translation helpful? Give feedback.
-
直接上DFS的preorder呢? class Solution:
def countNodes(self, root: Optional[TreeNode]) -> int:
self.c = 0
def preorder(node):
if node:
self.c += 1
preorder(node.left)
preorder(node.right)
preorder(root)
return self.c
|
Beta Was this translation helpful? Give feedback.
-
JavaScript 版本 var countNodes = function(root) {
// 比较有趣的思路:顶部的部分 用full二叉树的做法来做
// 最下面一层 用正常二叉树的思路来做?
let l = root,r = root
let leftH = 0,rightH = 0
// 计算左侧高度
while(l!=null){
l = l.left
leftH++
}
// 计算右侧高度
while(r!=null){
r = r.right
rightH++
}
// 如果高度相等,满二叉树
if(leftH == rightH){
return Math.pow(2,leftH)-1 // 这个实际上也充当了 base case 的角色
}
// 如果高度不相等,进行正常计算
return 1 + countNodes(root.left) + countNodes(root.right)
}; |
Beta Was this translation helpful? Give feedback.
-
「完全二叉树比普通二叉树特殊,但又没有满二叉树那么特殊」 |
Beta Was this translation helpful? Give feedback.
-
感觉复杂度如果用 O(log(N/2) + log(N/4) + .... + 1) 去表示可能更好理解些,完全二叉树的左右子树递归的去看的话,一定有一半是满二叉树,只有最后的一个枝叶是普通二叉树,那就是可以近似有 log(N) 个完全二叉树的递归,每一个log(N/xxx)可以近似成 log(N),那么 O(log(N/2) + log(N/4) + .... + 1) = O(log(N)*log(N)) 了 |
Beta Was this translation helpful? Give feedback.
-
文章链接点这里:如何计算完全二叉树的节点数
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions