EDIT : Cela ne répond pas à la contrainte de "l'espace constant" - cela double essentiellement l'espace requis. Je doute fort qu'il existe une solution qui n'a pas Cependant, il n'est pas possible de faire cela sans modifier la complexité de l'exécution (par exemple, en rendant push/pop O(n)). Notez que cela ne change pas le complexité de l'espace requis, par exemple, si vous avez une pile avec O(n) d'espace requis, ce sera toujours O(n), mais avec un facteur constant différent.
Solution de l'espace non-constant
Gardez une pile "dupliquée" de "minimum de toutes les valeurs inférieures dans la pile". Quand vous sortez la pile principale, sortez aussi la pile minimale. Lorsque vous poussez la pile principale, poussez soit le nouvel élément, soit le minimum actuel, celui qui est le plus bas. getMinimum()
est alors mis en œuvre comme juste minStack.peek()
.
Donc en utilisant votre exemple, nous aurions :
Real stack Min stack
5 --> TOP 1
1 1
4 2
6 2
2 2
Après avoir sauté deux fois, vous obtenez :
Real stack Min stack
4 2
6 2
2 2
Veuillez me faire savoir si ces informations ne sont pas suffisantes. C'est simple quand on le comprend, mais il faut parfois se creuser la tête au début :)
(L'inconvénient, bien sûr, est que cela double l'espace requis. Le temps d'exécution n'en souffre cependant pas de manière significative - c'est-à-dire que la complexité reste la même).
EDIT : Il existe une variante qui est légèrement plus compliquée, mais qui offre un meilleur espace en général. Nous avons toujours la pile min, mais nous ne sortons de celle-ci que lorsque la valeur que nous sortons de la pile principale est égale à celle de la pile min. Nous ne pousser à la pile principale lorsque la valeur poussée sur la pile principale est inférieure à ou égal à la valeur min actuelle. Cela permet de dupliquer les valeurs min. getMinimum()
n'est toujours qu'une simple opération de lecture. Par exemple, en prenant la version originale et en poussant 1 à nouveau, on obtiendrait.. :
Real stack Min stack
1 --> TOP 1
5 1
1 2
4
6
2
La sortie de la pile ci-dessus sort des deux piles parce que 1 == 1, ce qui laisse :
Real stack Min stack
5 --> TOP 1
1 2
4
6
2
Encore une fois sólo sort de la pile principale, car 5 > 1 :
Real stack Min stack
1 1
4 2
6
2
Un nouvel éclatement fait éclater les deux piles car 1 == 1 :
Real stack Min stack
4 2
6
2
Cela aboutit à la même complexité d'espace dans le pire des cas (le double de la pile d'origine) mais à une bien meilleure utilisation de l'espace si nous obtenons rarement un "nouveau minimum ou égal".
EDIT : Voici une implémentation du plan diabolique de Pete. Je ne l'ai pas testé à fond, mais je pensez à c'est bon :)
using System.Collections.Generic;
public class FastMinStack<T>
{
private readonly Stack<T> stack = new Stack<T>();
// Could pass this in to the constructor
private readonly IComparer<T> comparer = Comparer<T>.Default;
private T currentMin;
public T Minimum
{
get { return currentMin; }
}
public void Push(T element)
{
if (stack.Count == 0 ||
comparer.Compare(element, currentMin) <= 0)
{
stack.Push(currentMin);
stack.Push(element);
currentMin = element;
}
else
{
stack.Push(element);
}
}
public T Pop()
{
T ret = stack.Pop();
if (comparer.Compare(ret, currentMin) == 0)
{
currentMin = stack.Pop();
}
return ret;
}
}
0 votes
GeeksforGeeks Concevoir une pile qui supporte getMin() en O(1) temps et O(1) espace supplémentaire plus probable que non.