C 堆栈中的最小值

C 堆栈中的最小值,c,algorithm,data-structures,C,Algorithm,Data Structures,我有一个包含一些整数数据的堆栈。我想在O(1)时间内从堆栈中找出最小值。有什么想法吗 PS:堆栈中的数据没有顺序(增加/减少) 谢谢 Naveen堆栈定义为push/pop(LIFO)数据结构。您不能使用单个堆栈 O(n)是你要做的最好的-你必须检查每一个值并将它们与聚合器最小值进行比较,否则你怎么知道你得到了最小值 如果您愿意,您可以在添加值时存储最小值,使推送更为昂贵,以便进行O(1)读取(预先计算的最小值),但仅此而已。我不确定您为什么希望在恒定时间内对任意长度执行此操作。您最多只能使用两

我有一个包含一些整数数据的堆栈。我想在O(1)时间内从堆栈中找出最小值。有什么想法吗

PS:堆栈中的数据没有顺序(增加/减少)

谢谢


Naveen

堆栈定义为
push/pop
LIFO
)数据结构。您不能使用单个堆栈

O(n)是你要做的最好的-你必须检查每一个值并将它们与聚合器最小值进行比较,否则你怎么知道你得到了最小值


如果您愿意,您可以在添加值时存储最小值,使推送更为昂贵,以便进行O(1)读取(预先计算的最小值),但仅此而已。

我不确定您为什么希望在恒定时间内对任意长度执行此操作。您最多只能使用两个堆栈。一个是数据,一个是最小值。当您推到数据堆栈上时,将新的最小值推到最小值堆栈上(新的最小值是您正在推的项的最小值以及当前位于最小值堆栈顶部的任何值),当您弹出时,弹出两个堆栈(以便两个堆栈始终具有相同数量的元素)。要找到最小元素,只需查看最小值堆栈的顶部


按下、弹出和查找最小值都是O(1)。

如果要始终弹出最小的元素,可能需要某种类型的。如果您希望弹出上次推送的内容,但能够知道堆栈中剩余元素的顺序,则某种搜索树(例如)将支持从任意位置删除元素(堆栈将具有指向树节点的指针,以便在弹出时可以找到它)


如果您只需要知道堆栈中剩余的最小值(或最大值),那么ESRogs是最优的。

以下是使用列表作为堆栈的ESRogs算法的Python实现:

class ConstantStack:
    def __init__(self):
        self.stack = []
        self.min_stack = []
    def push(self,item):
        self.stack.append(item)
        if len(self.min_stack) == 0:
            self.min_stack.append(item)
            return
        # Get the smaller item between the pushed item and the top of the stack
        smallest = min(item,self.min_stack[-1])
        self.min_stack.append(smallest)
    def pop(self):
        self.min_stack.pop()
        return self.stack.pop()
    def min(self):
        # NOTE: min_stack[-1] is equivalent to peek()
        return self.min_stack[-1]
以下是其用法示例:

>>> s = ConstantStack()
>>> s.push(3)
>>> s.push(7)
>>> s.push(6)
>>> s.push(1)
>>> s.min()
1
>>> s.pop()
1
>>> # Now that 1 is gone, 3 is the next smallest
>>> s.min()
3
>>> s.pop()
6
>>> # 6 was popped but 3 still remains the smallest
>>> s.min()
3
>>> s.pop()
7
>>> s.min()
3
>>> s.pop()
3
#定义堆栈大小50
typedef结构堆栈
{
整数项[堆栈大小];
int top;
}MULSTACKEX;
void InitStack(MULSTACKEX&st)
{
st.item[STACKSIZE]=0;
st.top=-1;
}
无效推送(MULSTACKEX&st1、MULSTACKEX&st2、int elem)
{
如果(st1.top==-1)
{   
st1.top++;
st1.项目[st1.顶部]=元素;
st2.top++;
st2.项目[st2.顶部]=元素;
}
其他的
{
st1.top++;
st1.项目[st1.顶部]=元素;
如果(元素cout我们不推1个值,而是推一对数字。第一个元素是要推的元素,第二个元素是堆栈中的最小元素,我们应该跟踪最小元素。(元素,minOfStack)

假设您有一个空数组。当您第一次将数据推送到堆栈时,firs元素也是最小值

 data=[(1,1)]

然后添加值2。检查堆栈的minimim值为1,1堆栈上已经存在值。我只需要找出堆栈中的最小值。@Naveen:答案仍然是一样的。堆栈上有N个值,您必须查看所有值,以确定哪一个最小。这就是N个比较,所以计算充其量是O(N)。我相信你的意思是说:“让pops更昂贵”,因为在你的方法中,弹出可能会导致你不得不搜索一分钟。但正如已经建议的,你可以使用两个堆栈。另外,@Stephen C…你指的是N-1比较…仍然是O(N),尽管:-)。是的,我知道可以用O(N)完成时间。我只是想知道是否也可以在O(1)时间内完成。他说,我引用他的话,“你能做的最好的事情就是O(n)。“所以不,你不能在O(1)时间内完成。这个答案并不能真正回答问题。它回答的问题是“在n个元素列表中找到min的大O是什么?”。它没有说明堆栈数据结构或如何修改。可以说,也许我在广场上想得太多了;)但我严格地回答了这个问题“你能在恒定时间内找到堆栈的最小值吗?”如果你只有那个堆栈,那么答案是否定的。堆栈中的数据顺序根据定义完全取决于你推送的方式。你需要检查所有元素O(n)。如果推送的数据中有更多已知的东西,则可能存在异常。相关的,尽管我不确定它是否重复。@GMan:给出的解决方案“”需要O(n)我的问题是,我们能在O(1)中这样做吗.bravo:-)。打败我吧…每个人都说这是不可能的!我希望我能再次+1这个答案。我打赌你会从这一个中获得一些徽章:-)。一个更好的实现将保持最小值堆栈为1个元素,不管有多少个元素添加到另一个元素,但只有当你需要整个堆栈的最小值时,而不是任何“子堆栈”在堆栈中。@wrang-wrang:在常规堆栈上按1,在minStack上按1。在常规堆栈上按2,在minStack上按1。在常规堆栈上按3,在minStack上按1…如果你弹出一两次(从两个堆栈中),你仍然会在minStack顶部有正确的min值。有意义吗?@Chris Lutz:你能澄清一下吗?你不能在min堆栈上保留一个项目,因为这与将最小值存储在变量中是一样的……如果min从常规堆栈中弹出,你就不得不搜索新的最小值。实际上,你可以找到最小值如果您使用其他数据结构(例如,第二个堆栈)来保存弹出的值,则堆栈上的um值。但是N pops+N比较+N推送是O(N)。@Stephen I说“您不能!”执行“O(1)次”:
 data=[(1,1)]
data=[(1,1),(2,1)]
class StackTrackingMin:
    def __init__(self):
        self._data=[]
    def push(self,x:int)->None:
        currentMin=self.getMin()
        if currentMin==None or currentMin>x:
            currentMin=x
        self._data.append((x,currentMin))
    def pop(self)->None:
        self._data.pop() # pop does not return anything
    def top(self)->int:
        return self._date[-1] if self._data else None
    def getMin(self)->int:
        return self._data[-1][1] if self._data else None