计算具有给定高度的二叉树中的所有节点

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() 中看到leftright,可以很容易地删除它们,在heightaux 中看到hLefthRight,它们也可以删除,但不会牺牲一些效率。甚至有人可能会争辩说,辅助函数的参数违反了这一约束。 简单的 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;

【讨论】:

以上是关于计算具有给定高度的二叉树中的所有节点的主要内容,如果未能解决你的问题,请参考以下文章

给定规格的二叉树中节点的最优化位置是啥?

二叉树每个节点有一个权值,给定一棵二叉树,求权值和最大的值

十、二叉树(Binary Tree)

二叉树中的权值是啥?

二叉树中的权值是啥?

设计一个算法,计算出给定二叉树中任意2 个结点之间的最短路径。