2009-09-04 21 views
6

Tengo una pila que contiene algunos datos enteros. Quiero saber el valor mínimo de Stack en O (1) vez. ¿Alguna idea?Valor mínimo de la pila

PD: No se realiza ningún pedido (aumento/disminución) de datos en la pila.

Gracias,

Naveen

+0

orden de los datos en la pila por definición puramente dependiente cómo empujas Necesito verificar todos los elementos O (n). La excepción puede estar allí si hay algo más conocido con respecto a los datos que se envían. – Learner

+0

Relacionado, aunque no estoy seguro de que dijera que fue un duplicado. http://stackoverflow.com/questions/1042507/finding-smallest-value-in-an-array-most-efficiently/1042523#1042523 – GManNickG

+0

@GMan: La solución dada "http://stackoverflow.com/questions/1042507/finding-smallest-value-in-an-array-most-efficient/1042523 # 1042523 "toma O (n). Mi pregunta es, ¿podemos hacer esto en O (1). – Naveen

Respuesta

28

Use dos pilas. Uno es los datos, uno son los mínimos. Cuando ingresa a la pila de datos, inserte el nuevo mínimo en la pila de mínimos (el nuevo mínimo es el mínimo del artículo que está presionando y lo que está actualmente en la parte superior de la pila de mínimos), y cuando salga, estallará de ambas pilas (para que las dos pilas siempre tengan la misma cantidad de elementos). Para encontrar el elemento mínimo, solo mira la parte superior de la pila de mínimos.

Empujar, abrir y encontrar el valor mínimo son O (1).

+0

bravo :-). golpéame ... ¡y todos dijeron que era imposible! – Tom

+0

Ojalá pudiera +1 esta respuesta de nuevo. Apuesto a que ganarás algunas insignias de esta :-). – Tom

+0

@ wrang-wrang, ¿por qué? – Tom

2

Una pila por definición es push/pop (LIFO) estructura de datos. ¡No puedes usar una sola pila!

+0

En realidad, puede encontrar el valor mínimo en una pila, si usa alguna otra estructura de datos (por ejemplo, una segunda pila) para guardar los valores reventados. Pero N pops + N comparaciones + N empuja es O (N). –

+0

@Stephen dije "¡No puedes!" do "O (1) time" :) – AraK

2

O (n) es lo mejor que vas a hacer - deberías verificar cada uno de los valores y compararlos con el mínimo del agregador, de lo contrario, ¿cómo sabrías que obtuviste el más bajo?

Si lo desea, puede almacenar el mínimo a medida que se agregan los valores, haciendo que los empujes sean más caros en beneficio de una lectura O (1) (del mínimo precalculado), pero eso es todo.

+0

Los valores ya están allí en la pila. Solo tengo que averiguar el valor mínimo en la Pila. – Naveen

+0

@Naveen: la respuesta sigue siendo la misma. Hay N valores en la pila y tienes que mirarlos a todos para descubrir cuál es el más pequeño. Eso es N comparaciones, por lo que el cálculo es en el mejor de los casos O (N). –

+0

Creo que quisiste decir: "hacer los pops más caros", porque en tu enfoque, hacer pops podría hacer que tengas que buscar un mínimo. Pero como ya se sugirió, puedes usar dos pilas. – Tom

1

No estoy seguro de por qué esperas hacer esto en tiempo constante por longitud arbitraria. Lo mejor que podrá hacer es O (n)

+0

Sí, sé que se puede hacer en O (n) vez. Solo quiero saber si también es posible hacerlo en O (1) vez. – Naveen

+4

Dijo, y cito: "Lo mejor que podrás hacer es O (n)". Entonces no, no puedes hacerlo en O (1). –

+0

Esta respuesta realmente no responde la pregunta. Está respondiendo a la pregunta de "¿cuál es el big-o para encontrar el mínimo en una lista de elementos?". No dice nada sobre la estructura de datos de la pila o cómo se puede modificar. – Tom

1

Probablemente querrá algún tipo de priority heap si siempre desea mostrar el elemento menos. Si desea mostrar lo que se presionó por última vez, pero debe saber el orden de los elementos que quedan en la pila, algún tipo de árbol de búsqueda, p. red-black admitirá la eliminación de un elemento desde una posición arbitraria (su pila tendría un puntero al nodo de árbol para que cuando aparezca puede encontrarlo).

Si solo necesita saber el mínimo (o máximo) que queda en la pila, ESRogs 'es óptimo.

1

Aquí está la implementación de Python del algoritmo ESRogs el uso de listas como pilas:

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] 

Aquí es un ejemplo de su uso:

>>> 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 
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; 
} 
Cuestiones relacionadas