Data structures 为了遍历| |调用堆栈空间,是否考虑?

Data structures 为了遍历| |调用堆栈空间,是否考虑?,data-structures,tree,tree-traversal,space-complexity,inorder,Data Structures,Tree,Tree Traversal,Space Complexity,Inorder,这个问题已经在我脑海中出现了很多天,我希望有人能澄清它。 问题:-查找二叉树中的节点数 方法1:-(迭代法) 使用堆栈进行顺序遍历。无论何时从堆栈中弹出元素,都要对其进行计数,即二叉树中的节点数 时间复杂度-O(n) 空间复杂度-O(n) 方法2:-(递归的) 时间复杂度-O(n) 空间复杂度-O(1)或O(n) 我们可以递归地进行顺序遍历,但在面试中,哪种方法对面试官来说是最佳表达方式……迭代还是递归??我还应该考虑递归调用栈空间,它将空间复杂度归结为O(n)还是应该坚持O(1)空间复杂度?

这个问题已经在我脑海中出现了很多天,我希望有人能澄清它。 问题:-查找二叉树中的节点数

方法1:-迭代法) 使用堆栈进行顺序遍历。无论何时从堆栈中弹出元素,都要对其进行计数,即二叉树中的节点数

时间复杂度-O(n)

空间复杂度-O(n)

方法2:-递归的

时间复杂度-O(n)

空间复杂度-O(1)或O(n)

我们可以递归地进行顺序遍历,但在面试中,哪种方法对面试官来说是最佳表达方式……迭代还是递归??我还应该考虑递归调用栈空间,它将空间复杂度归结为O(n)还是应该坚持O(1)空间复杂度?

你的问题——“哪种方法对面试者来说是最佳表达”——除了面试官自己之外,谁也不能真正回答。然而,解决这个问题的可能方法之间的差异值得讨论


首先,让我们注意到迭代和递归方法都使用堆栈;迭代方法有一个显式堆栈,但递归函数使用一个不由程序员管理的堆栈工作。因此,两种方法使用的辅助空间都是渐近相同的,但迭代方法的常数较低,因为它只将节点推送到堆栈,而递归方法推送到整个调用帧,包括所有局部变量

注意,辅助空间是O(h),其中h是树的高度,而不是O(n),其中n是节点数。这一点很重要,因为最坏的情况取决于树是否正确。对于不平衡树,最坏情况下的高度h为O(n),而对于平衡树,h为O(logn)。这个问题并没有指定树是平衡的,所以当树的高度太大时,递归方法会有风险。相反,迭代方法在主内存中存储显式堆栈


这都是关于效率的讨论,但编程不仅仅是算法效率。例如,如果树永远不会很大,您可能更喜欢递归方法,因为它编写起来更简单;它只需要几行非常干净的代码。命令式方法需要创建一个堆栈,并在循环中从中推送和弹出,因此代码可能会更长,更难理解。不要低估干净易懂的代码的价值


另一件事是,您直接跳到顺序遍历作为问题的解决方案,但是如果问题是计算二叉树中的节点数,那么您可以按任意顺序遍历它。预顺序遍历比顺序遍历更易于迭代实现,而且同样高效


或者,如果数据结构本身可以修改,那么给每个节点一个包含其子树基数的属性就很简单了。插入、删除和重新平衡操作需要修改以维护此属性,但额外的工作是O(1),它允许通过读取根节点的基数属性以O(1)计算树的大小。添加此属性还有其他好处,例如支持在O(h)时间内而不是在O(h+k)时间内执行“查找第k个节点”操作。

是的,在考虑空间复杂性时,应该计算调用堆栈。注意,两种算法的空间复杂度都是O(h),其中h是树的高度;不是O(n),其中n是节点数。@kaya3那么在这种情况下,为了找到节点数,堆栈方法也很好,对吧???哇。。。这是一些明确的解释。。。非常感谢您花时间解释清楚。