以下函数在二叉树上运行。该函数将获取指向树根的指针和非负int k。它应该从根返回节点k深度。
struct treenode {
int data;
struct treenode* left;
struct treenode* right;
}
int numNodesHeightK(struct treenode* root, int k){
if(root == NULL) return 0; //if the tree is empty return 0
if(k == 0) return 1; //if k = 0, then the root is the only node to return
//How does this statement work?
return numNodesHeightK(root->left, k-1) + numNodesHeightK(root->right, k-1);
}
如果有人能够解释最终陈述的逻辑。我没有看到这行代码如何返回正确的深度。
答案 0 :(得分:3)
对于每个节点,您希望将每个子树的深度为k
的节点数加在一起。这意味着从各自的根(当前节点的左右子树)遍历深度为k-1
的节点的子树。当k
到达0
时,这意味着返回该节点的1
- 因为它是原始根的深度k
。
最后一个语句完成此操作 - 首先遍历左子树,然后遍历右子树,从当前节点查找深度为k
的节点数,将它们相加,然后返回结果。
该算法非常简单 - 在纸上绘制测试树并逐步完成。逻辑应该很快就会向你跳出来。
答案 1 :(得分:1)
理论上,给定深度处的节点总数(假设深度= 5)与从左子节点和右子节点计数的深度= 4的节点的总和相同。 (因为搬到孩子身上已经引入了1的深度。)
所以,让我们在左子上找到深度为4的节点数:
numNodesHeightK(root->left, k-1)
右子上的深度为4的节点数:
numNodesHeightK(root->right, k-1)
并将它们添加到一起以获得从当前节点获取深度5的节点数的答案。
仅这一点并没有解决问题,它只是把它分解成两个更简单,更小的部分。直到你要求深度0处的节点数量明显为1时,问题才会完全解决。这是在函数的基本情况中实现的:
if(k == 0) return 1; //if k = 0, then the root is the only node to return
最后,你可以互换地使用术语“高度”和“深度”,如果你试着谈论“向下”或“向上”树,这会让人感到困惑。选择一个约定并坚持下去。
答案 2 :(得分:1)
只是递归地想一想......
一个子树中有多少个节点,其中roor为null
? 0
if (root == NULL) return 0;
深度为0的节点下有多少个节点? 1
(节点本身)。
if (k == 0) return 1;
有多少节点和子节点有树?左侧分支上的节点加上右侧分支上的节点。每个分支都处于较低级别。
// left side
numNodesHeightK(root->left, k-1) +
// right side
numNodesHeightK(root->right, k-1)
答案 3 :(得分:0)
描绘一幅如何运作的图片......
想想你是否有这个小组执行任务,并且有这些隧道继续向两个子通道分叉。我们的目标是找出这么多的叉子,这些叉子可以通向一个洞穴。货叉之间的距离是一个长度单位。
每当你到达隧道中的一个分支时,该分支的当前组将分成两半并将每一半分别发送到两个子通道。
每当小组分开K次时,他们就会停下来看看这个位置。然后他们回到水面,每个人都告诉他是否找到距离入口k的房间。如果任何子团队在距离k之前到达死胡同,他们会返回并说没有空间。
他们将总数加起来并向您汇报。
房间是节点。分叉是每个节点的子节点。子团队是你的方法在堆栈上的调用。
答案 4 :(得分:0)
单独理解这一行是不可能的,因为函数是递归的,而且一行是递归的那一行。
但是只有三行,所以我们可以很容易地了解整个事物。
为了计算给定深度的节点,有必要将树遍历到该深度。
这意味着我们递归地采用每个左右分支。
如果我们从叶子节点向下遍历到空节点,我们只返回0.如果我们发现自己处于正确的深度,我们可以阻止任何无意义的遍历在树中并且只返回1,因为我们的实例递归函数已落在目标深度的单个节点上。这条线阻止我们不必要地穿越,以及为我们所在的分支提供计数。
最后,你的最后一行。在每个更浅的层次上,有必要深入到树中,并且在递归实现中通过为树的每个分支调用函数的新实例来完成。该行可以由被调用实例再次执行,直到调用图本身累积镜像实际树,并且每个级别将更大的合并总和返回到先前级别,最终从单个实例返回单个可能相当大的数字。顶级节点。