如何计算完全二叉树的节点数 :: 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.
-
确实吊 |
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.
-
打卡 ”完全二叉树的左右两边,总有一个是满的“ 有趣 |
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.
-
东哥牛! |
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.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
文章链接点这里:如何计算完全二叉树的节点数
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions