计算具有给定高度的二叉树中的所有节点
Posted
技术标签:
【中文标题】计算具有给定高度的二叉树中的所有节点【英文标题】:Count all nodes in a binary tree with a given height 【发布时间】:2021-10-10 16:07:25 【问题描述】:我得到了一个练习,要求我创建一个算法,计算树中给定高度处的所有节点,其中高度定义为“节点的高度是从节点到更远的节点的最大距离叶”(我不能使用其他数据结构,甚至不能使用整数)这是我的解决方案:
int heightaux(Node u)
if(u == NULL) return -1;
int hLeft = 1 + heightaux(u->left);
int hRight = 1 + heightaux(u->right);
if(hLeft > hRight) return hLeft;
return hRight;
int height(Node u, int k)
if(u == NULL) return 0;
int left = height(u->left, k);
int right = height(u->right, k);
return left + right + (heightaux(u) == k);
这里的时间复杂度是O(nlog(n))
有没有办法优化这个?如果我可以编写一个使用空间复杂度 O(1)
的附加数据结构的算法,解决方案将如何变化?
二叉树示例:
5
1 9
6 10
k = 0 应该输出 3,因为节点 1、6 和 10 的高度 = 0
k = 1 应该输出 1,因为只有节点 9 的高度 = 1
k = 2 应该输出 1,因为只有节点 5 的高度 = 2
【问题讨论】:
您确定您正确解释了问题,尤其是“在树的给定高度”部分吗?您似乎将问题解释为“计算高度 k 的子树的数量”,这是一个公平的问题,但对于提出的约束,“计算深度 k 的节点数”(即距离根节点正好 k 步的节点数)似乎是一个更可能的问题。 说到约束,如果你不能使用额外的数据结构,甚至不能使用整数,那么提出的解决方案似乎是无效的。我在函数height()
中看到left
和right
,可以很容易地删除它们,在heightaux
中看到hLeft
和hRight
,它们也可以删除,但不会牺牲一些效率。甚至有人可能会争辩说,辅助函数的参数违反了这一约束。
简单的 dfs 遍历应该是 O(n) 时间和 O(n) 空间(注意:由于递归将值存储在堆栈中,每次调用都会占用空间,因为在最坏的情况下,我们有高度不平衡的树 n 空间总是至少 O(n)) int dfs(node c, int h)return c == NULL ? 0 : !h + dfs(node.L, h-1) + dfs(node.R, h-1);
您的代码似乎在 O(n^2) 时间内计算大小为 k
的子树(二叉树不一定是平衡的)
你还有其他关于树的信息吗?指定它是二进制似乎是一种浪费。 (即 complete?) 你怎么得到O(n log n)
?
@Neil:N 叉树很难编写代码。
【参考方案1】:
此答案已过时,因为该问题已被删除。如果不是因为 OP 在对此答案的评论中提供了对问题定义的更新,而不是在应有的问题中(我在其中编辑),我现在将删除此答案。 OP 要求的将是 O(可怕),他在问题正文中给出的答案很可能无法改进以获得更好的 O()。
原文如下:
这里假设高度 = 深度。
int count_height(Node u, int k)
if(u == NULL) return 0;
if(k < 0) return 0;
if(k-- == 0) return 1;
return count_height(u->left, k) + count_height(u->right, k)
只要下树,停在要求的高度。
如果解释是从最深的节点测量,我们可以这样做:
int count_depth(Node u, int k)
if(u == NULL) return 0;
if(k < 0) return 0;
if(k-- == 0) return 1;
return height(u->left, k) + height(u->right, k)
int max_depth(Node u)
if (u == NULL) return -1;
return maxi(max_depth(u->left), max_depth(u->right));
int count_height(Node u, int h)
return count_depth(u, max_depth(u) - h);
其中maxi
是作为函数的整数最大值。作为宏会太慢。
【讨论】:
感谢您的帮助,但是如果我给 k = 0,我发现在帖子中给定二叉树的算法存在问题,输出为 1,但它应该为 3,因为 1、6 和 10 height = 0 也许我的理论错了? @Stecco:我想不出二叉树高度的定义,也想不出与您添加到问题中的描述相匹配的用例。我通常会怀疑你误解了一些东西。 我现在已经阅读了我的教授给出的树中节点高度的定义:“节点的高度是从节点到更远的叶子的最大距离”也许在那里定义之间有区别吗?【参考方案2】:在 O(n) 时间内执行此操作的诀窍是您需要对每个节点进行一次递归调用,但它返回的信息取决于其高度:
int countNodesWithHeight(Node root, int k)
// k+1 here, because you want to find leaves when k==0.
// I need to consider nulls to have height 0 and leaves height 1
int count = countOrMinusHeight(root, k+1);
return count < 0 ? 0 : count;
// If root has height >= h, return count of nodes within root (at least 1)
// with height h. Otherwise, return negated height of root.
int countOrMinusHeight(Node root, int h)
if (root == null)
return h==0 ? 1 : 0;
int l = countOrMinusHeight(root.left, h);
int r = countOrMinusHeight(root.right, h);
if (l >= 1 || r >= 1)
// root has height > h
// add the counts from its children
return (l>=1 ? l:0) + (r>=1 ? r:0);
// root has height <= h
int rootHeight = (l<r ? 1-l : 1-r);
return rootHeight == h ? 1 : -rootHeight;
【讨论】:
以上是关于计算具有给定高度的二叉树中的所有节点的主要内容,如果未能解决你的问题,请参考以下文章