Stack的最小值

时间:2009-09-04 04:26:20

标签: c algorithm data-structures

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

PS:Stack中没有数据的排序(增加/减少)。

谢谢,

纳温

8 个答案:

答案 0 :(得分:28)

使用两个堆栈。一个是数据,一个是最小值。当您按下数据堆栈时,将新的最小值推到最小堆栈上(新的最小值是您正在推送的项目的最小值以及当前位于最小值堆栈顶部的任何内容),当您弹出时,弹出两个堆栈(以便两个堆栈始终具有相同数量的元素)。要查找最小元素,只需查看最小堆栈的顶部。

推送,弹出和找到最小值是O(1)。

答案 1 :(得分:2)

根据定义,堆栈是push/popLIFO)数据结构。你不能使用一个堆栈!

答案 2 :(得分:2)

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

如果你愿意,可以在添加值时存储最小值,为了O(1)读取(预先计算的最小值)的优势,使推送更加昂贵,但就是这样。

答案 3 :(得分:1)

我不确定为什么你希望在任意长度的恒定时间内这样做。你能做的最好的是O(n)

答案 4 :(得分:1)

如果你想永远弹出最少的元素,你可能想要某种priority heap。如果你想弹出最后推送的内容,但能够知道堆栈中剩余元素的顺序,可以使用某种搜索树,例如red-black将支持从任意位置删除元素(您的堆栈将具有指向树节点的指针,因此当您弹出时可以找到它)。

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

答案 5 :(得分:1)

以下是使用列表作为堆栈的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

答案 6 :(得分:0)

#define STACKSIZE 50

typedef struct stack
{
    int item[STACKSIZE];
    int top;
}MULSTACKEX;

void InitStack(MULSTACKEX &st)
{
   st.item[STACKSIZE] = 0;
   st.top = -1;
}

void Push(MULSTACKEX &st1, MULSTACKEX &st2, int elem)
{
    if(st1.top == -1)
    {   
        st1.top++;
        st1.item[st1.top] = elem;

        st2.top++;
        st2.item[st2.top] = elem;
    }
    else
    {
        st1.top++;
        st1.item[st1.top] = elem;

        if(elem < st2.item[st2.top])
        {
            st2.top++;
            st2.item[st2.top] = elem;
        }
    }
}

void Display(MULSTACKEX &st1, MULSTACKEX &st2)
{
    cout<<"stack1 elements: "<<endl;
    for(int i = 0; i <= st1.top; i++)
    {
        cout<<st1.item[i]<<"->";
    }

    cout<<endl;
    cout<<"stack2 elements: "<<endl;
    for(int i = 0; i <= st2.top; i++)
    {
        cout<<st2.item[i]<<"->";
    }

}

int Pop(MULSTACKEX &st1, MULSTACKEX &st2)
{
    int elem = 0;
    if(st1.item[st1.top] == st2.item[st2.top])
    {
        elem = st2.item[st2.top];
        st2.top--;

        elem = st1.item[st1.top];
        st1.top--;
    }
    else
    {
        elem = st1.item[st1.top];
        st1.top--;
    }

    return elem;    
}
int FindMin(MULSTACKEX &st2)
{
    int elem = st2.item[st2.top];
    return elem;
}

int _tmain(int argc, _TCHAR* argv[])
{
    MULSTACKEX stack1, stack2;

    InitStack(stack1); 
    InitStack(stack2);


    Push(stack1,stack2,13); 
    Push(stack1,stack2,17);
    Push(stack1,stack2,5);
    Display(stack1,stack2);

    int min_elem1 = FindMin(stack2);
    cout<<"Min element in the list is: "<<min_elem1<<endl<<endl;

    int deletedelem2 = Pop(stack1,stack2);
    cout<<"Pop element from the stack:"<< deletedelem2 <<endl<<endl;
    Display(stack1,stack2);

    cout<<endl<<endl;

    Push(stack1,stack2,19);
    Push(stack1,stack2,8);
    Display(stack1,stack2);

    cout<<endl<<endl;

    int deletedelem1 = Pop(stack1,stack2);
    cout<<"Pop element from the stack:"<< deletedelem1 <<endl<<endl;
    Display(stack1,stack2);

    int min_elem2 = FindMin(stack2);
    cout<<"Min element in the list is: "<<min_elem2<<endl<<endl;

    return 0;
}

答案 7 :(得分:0)

我们不是推送 1 个值,而是推送一对数字。第一个元素将是您要推送的元素,第二个元素将是堆栈的最小元素,我们应该跟踪最小元素。 (element,minOfStack)

假设你有一个空数组。首次入栈时,第一个元素也是最小值。

 data=[(1,1)]

然后添加值 2。检查堆栈的最小值为 1, 1<2,因此将 (2,1) 推入数组

data=[(1,1),(2,1)]

这里是python的实现

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