Algorithm 递归及其内存使用

Algorithm 递归及其内存使用,algorithm,data-structures,stack,Algorithm,Data Structures,Stack,我最近看到一个问题,它需要。在O(1)空间中反转堆栈 1) 堆栈不一定是一个数组。。。我们无法访问索引。 2) 元素的数量未知 我提出了下面的代码,它正在工作,但不确信它是O(1)空间,因为我已经声明了n次“int temp”(假设堆栈中最初有n个元素),所以它占用了O(n)空间。 请告诉我是对的还是错的,有没有更好的办法找到解决办法 代码: #包括 使用名称空间std; 斯塔克斯特; void rec() { if(st.empty()) 返回; int temp=st.top(); 圣普()

我最近看到一个问题,它需要。在O(1)空间中反转堆栈

1) 堆栈不一定是一个数组。。。我们无法访问索引。
2) 元素的数量未知

我提出了下面的代码,它正在工作,但不确信它是O(1)空间,因为我已经声明了n次“int temp”(假设堆栈中最初有n个元素)
,所以它占用了O(n)空间。

请告诉我是对的还是错的,有没有更好的办法找到解决办法

代码:

#包括
使用名称空间std;
斯塔克斯特;
void rec()
{
if(st.empty())
返回;
int temp=st.top();
圣普();
rec();
圣普什(临时);
}
int main()
{
圣普什(1);
圣普什(2);
圣普什(3);
圣普什(4);
rec();
}

我能想到的唯一方法是使用链表编写自己的堆栈,然后交换头/尾指针和一个“方向”指示器,当你按下/弹出时,它会告诉你的例程前进或后退。我能想到的任何其他方法都是O(n)

如果知道n的上限,还可以使用数组/索引而不是列表


这样做是否有意义可能取决于这样做的原因和语言。

您可以在一个包含n个元素的数组中构建两个堆栈“背靠背”。基本上,堆栈#1是一个“普通”堆栈,而堆栈#2从数组的末尾开始“向下”增长

每当两个堆栈一起包含所有n个元素时,它们之间就没有间隙,因此,例如,在这种情况下,从堆栈#1弹出一个元素并立即将其推到堆栈#2上,甚至无需移动任何数据即可完成:只需向下移动堆栈#1的
top
指针,堆栈2的
top
指针物理上向下(但逻辑上向上)

假设我们从堆栈#1中的所有元素开始。现在,您可以弹出除最后一个之外的所有文件,立即将每个文件推到堆栈#2上。最后一个元素可以弹出并存储在临时位置x(O(1)个额外的存储,这是允许的)。现在弹出堆栈#2中的所有n-1项,依次将每个项推回堆栈#1,然后最后将x推回(现在为空)堆栈#2。此时,我们成功地删除了堆栈#1中的底部元素,并将其放在堆栈#2的顶部(嗯,它是堆栈#2中唯一的元素)

现在只需递归:假设我们只有n-1项,然后解决这个小问题。继续递归,直到所有元素都按相反顺序推送到堆栈#2上。在最后一个步骤中,将它们分别弹出并推回到堆栈#1上


总而言之,O(n^2)步骤是必需的,但我们仅使用O(1)空间进行管理。

是的-我认为您在这个解决方案中使用了O(n)空间。您是正确的,这是
O(n)
空间,但我不知道如何使用
O(1)
空间来实现这一点。从堆栈中获取底部元素的唯一方法是首先从其他元素中取出,这些元素需要存储在某个地方。根据恒定的空间要求,存储它们的唯一位置是在初始堆栈上,但是您无法到达最后一个元素。。。我想说你的解决方案就是他们在问题中的意思,但是他们没有意识到递归也使用了一个
O(n)
size的堆栈…不管怎样,即使没有int-temp,你也在用递归调用创建n个堆栈帧,如果我没记错的话,如果你从一个堆栈中弹出元素并将它们推到另一个堆栈中-可能是O(1)在内存方面(如果堆栈实现为链表)。然而,这一理论与实践几乎没有什么联系。@MateuszDymczyk我只关心
temp变量的初始化。
创建n个堆栈帧而言
我认为我们可以将堆栈作为参考传递并避免它?
#include<bits/stdc++.h>
using namespace std;
stack<int>st;
void rec()
{
    if(st.empty()) 
        return;
    int temp=st.top();
    st.pop();

    rec();
    st.push(temp);
}
int main()
{
    st.push(1);
    st.push(2);
    st.push(3);
    st.push(4);

    rec();
}