EDIT: Cela échoue à la contrainte "espace constant" - cela double essentiellement l'espace requis. Je doute fort qu'il existe une solution qui ne fasse pas cela, sans gâcher quelque part la complexité d'exécution (par exemple, faire push / pop O (n)). Notez que cela ne change pas la complexité de l'espace requis, par exemple si vous avez une pile avec des exigences d'espace O (n), ce sera toujours O (n) avec un facteur constant différent.
Solution à espace non constant
Gardez une pile "dupliquée" de "minimum de toutes les valeurs inférieures dans la pile". Lorsque vous ouvrez la pile principale, faites également apparaître la pile min. Lorsque vous poussez la pile principale, appuyez soit sur le nouvel élément, soit sur le min courant, selon la valeur la plus basse. getMinimum()
est alors implémenté 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 vous le grokez, mais cela peut prendre un peu de grattage au début :)
(L'inconvénient bien sûr est que cela double l'espace requis. Le temps d'exécution ne souffre pas de manière significative - c'est-à-dire qu'il est toujours de la même complexité.)
EDIT: Il y a une variante qui est un peu plus compliquée, mais qui a un meilleur espace en général. Nous avons toujours la pile min, mais nous n'en sortons que lorsque la valeur que nous sortons de la pile principale est égale à celle de la pile min. Nous ne poussons vers la pile min que lorsque la valeur poussée sur la pile principale est inférieure ou égale à la valeur min actuelle. Cela permet de dupliquer les valeurs minimales. getMinimum()
est encore juste une opération de coup d'oeil. Par exemple, en prenant la version originale et en poussant à nouveau 1, nous obtiendrions:
Real stack Min stack
1 --> TOP 1
5 1
1 2
4
6
2
Popping à partir de ce qui précède apparaît des deux piles car 1 == 1, laissant:
Real stack Min stack
5 --> TOP 1
1 2
4
6
2
Le pop à nouveau n'apparaît que de la pile principale, car 5> 1:
Real stack Min stack
1 1
4 2
6
2
Popping à nouveau fait apparaître 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 mise en œuvre du plan diabolique de Pete. Je ne l'ai pas testé à fond, mais je pense que ça va :)
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;
}
}
Ajoutez un champ pour contenir la valeur minimale et mettez-le à jour pendant Pop () et Push (). De cette façon, getMinimum () sera O (1), mais Pop () et Push () devront faire un peu plus de travail.
Si la valeur minimale est sautée, Pop () sera O (n), sinon ils seront toujours tous les deux O (1). Lors du redimensionnement, Push () devient O (n) selon l'implémentation de Stack.
Voici une mise en œuvre rapide
la source
Il stocke explicitement le minimum actuel, et si le minimum change, au lieu de pousser la valeur, il pousse une valeur de la même différence de l'autre côté du nouveau minimum (si min = 7 et que vous appuyez sur 5, il pousse 3 à la place (5- | 7-5 | = 3) et définit min à 5; si vous pop 3 quand min est 5, il voit que la valeur popped est inférieure à min, donc inverse la procédure pour obtenir 7 pour le nouveau min, puis retourne le précédent min). Comme toute valeur qui n'entraîne pas de changement, le minimum actuel est supérieur au minimum actuel, vous avez quelque chose qui peut être utilisé pour différencier les valeurs qui changent le minimum et celles qui ne le font pas.
Dans les langages qui utilisent des entiers de taille fixe, vous empruntez un peu d'espace à la représentation des valeurs, de sorte que cela risque de déborder et que l'assertion échouera. Mais sinon, c'est un espace supplémentaire constant et toutes les opérations sont toujours O (1).
Les piles basées sur des listes chaînées ont d'autres emplacements auxquels vous pouvez emprunter un peu, par exemple en C le bit le moins significatif du pointeur suivant, ou en Java le type des objets dans la liste chaînée. Pour Java, cela signifie qu'il y a plus d'espace utilisé par rapport à une pile contiguë, car vous avez la surcharge d'objet par lien:
En C, la surcharge n'est pas là, et vous pouvez emprunter le lsb du pointeur suivant:
Cependant, aucun de ceux-ci n'est vraiment O (1). Ils ne nécessitent plus d'espace en pratique, car ils exploitent des trous dans les représentations de nombres, d'objets ou de pointeurs dans ces langages. Mais une machine théorique qui utilisait une représentation plus compacte exigerait un bit supplémentaire à ajouter à cette représentation dans chaque cas.
la source
pop()
si la dernière valeur poussée étaitInteger.MIN_VALUE
(par exemple, push 1, push Integer.MIN_VALUE, pop). Cela est dû au sous-débordement comme mentionné ci-dessus. Sinon, fonctionne pour toutes les valeurs entières.J'ai trouvé une solution qui satisfait toutes les contraintes mentionnées (opérations à temps constant) et espace supplémentaire constant .
L'idée est de stocker la différence entre la valeur min et le nombre d'entrée, et de mettre à jour la valeur min si elle n'est plus la valeur minimale.
Le code est comme suit:
Le crédit va à: https://leetcode.com/discuss/15679/share-my-java-solution-with-only-one-stack
la source
Eh bien, quelles sont les contraintes d'exécution de
push
etpop
? S'ils ne sont pas tenus d'être constants, calculez simplement la valeur minimale de ces deux opérations (en les rendant O ( n )). Sinon, je ne vois pas comment cela peut être fait avec un espace supplémentaire constant.la source
Voici mon code qui fonctionne avec O (1). Le code précédent que j'ai publié avait un problème lorsque l'élément minimum est apparu. J'ai modifié mon code. Celui-ci utilise une autre pile qui maintient l'élément minimum présent dans la pile au-dessus de l'élément poussé actuel.
la source
J'ai utilisé un autre type de pile. Voici la mise en œuvre.
Production:
Essayez-le. Je pense que cela répond à la question. Le deuxième élément de chaque paire donne la valeur minimale vue lorsque cet élément a été inséré.
la source
Je poste le code complet ici pour trouver le minimum et le maximum dans une pile donnée.
La complexité temporelle sera O (1).
Faites-moi savoir si vous rencontrez un problème
Merci, Vikash
la source
Vous pouvez étendre votre classe de pile d'origine et y ajouter simplement le suivi minimum. Laissez la classe parent d'origine gérer tout le reste comme d'habitude.
la source
Voici ma solution en java en utilisant la liste aimée.
}
la source
Supposons que la pile sur laquelle nous allons travailler est la suivante:
Dans la représentation ci-dessus, la pile n'est construite que par la valeur gauche, la valeur [minvalue] de droite est écrite uniquement à des fins d'illustration qui sera stockée dans une variable.
Le problème réel est lorsque la valeur qui est la valeur minimale est supprimée à ce stade, comment pouvons-nous savoir quel est le prochain élément minimum sans itérer sur la pile.
Comme par exemple dans notre pile lorsque 6 get apparaît, nous savons que ce n'est pas l'élément minimum car l'élément minimum est 2, nous pouvons donc le supprimer en toute sécurité sans mettre à jour notre valeur min.
Mais lorsque nous pop 2, nous pouvons voir que la valeur minimale est de 2 pour le moment et si cela apparaît, nous devons mettre à jour la valeur minimale à 3.
Point1:
Maintenant, si vous observez attentivement, nous devons générer minvalue = 3 à partir de cet état particulier [2, minvalue = 2]. ou si vous allez depper dans la pile, nous devons générer minvalue = 7 à partir de cet état particulier [3, minvalue = 3] ou si vous allez plus loin dans la pile, nous devons générer minvalue = 8 à partir de cet état particulier [7, minvalue = 7]
Avez-vous remarqué quelque chose en commun dans tous les 3 cas ci-dessus, la valeur que nous devons générer dépend de deux variables qui sont toutes deux égales. Correct. Pourquoi cela se produit-il parce que lorsque nous poussons un élément plus petit que la valeur minimale actuelle, nous poussons essentiellement cet élément dans la pile et mettons également à jour le même nombre dans la valeur minimale.
Point2:
Nous stockons donc essentiellement un double du même nombre une fois dans la pile et une fois dans la variable minvalue. Nous devons nous concentrer pour éviter cette duplication et stocker des données utiles dans la pile ou la valeur min pour générer le minimum précédent, comme indiqué dans CASES ci-dessus.
Concentrons-nous sur ce que nous devons stocker dans la pile lorsque la valeur à stocker dans push est inférieure à la valeur minmum. Appelons cette variable y, donc maintenant notre pile ressemblera à ceci:
Je les ai renommés y1, y2, y3 pour éviter toute confusion selon laquelle tous auront la même valeur.
Point3:
Essayons maintenant de trouver des contraintes sur y1, y2 et y3. Vous souvenez-vous quand exactement nous avons besoin de mettre à jour la valeur min en faisant pop (), seulement quand nous avons sauté l'élément qui est égal à la valeur min. Si nous affichons quelque chose de plus grand que la valeur minimale, nous n'avons pas besoin de mettre à jour la valeur minimale. Donc, pour déclencher la mise à jour de la valeur min, y1, y2 et y3 doivent être plus petits que la valeur min correspondante. [Nous avodons l'égalité pour éviter la duplication [Point2]] donc la contrainte est [y <minValue].
Revenons maintenant à peupler y, nous devons générer une valeur et mettre y au moment du push, rappelez-vous. Prenons la valeur qui vient pour push pour être x qui est inférieure à la prevMinvalue, et la valeur que nous allons réellement pousser dans la pile pour être y. Une chose est donc évidente: newMinValue = x et y <newMinvalue.
Maintenant, nous devons calculer y (rappelez-vous que y peut être n'importe quel nombre inférieur à newMinValue (x), nous devons donc trouver un nombre qui puisse remplir notre contrainte) à l'aide de prevMinvalue et x (newMinvalue).
Donc, au moment de pousser x s'il est inférieur à prevMinvalue, nous poussons y [2 * x-prevMinValue] et mettons à jour newMinValue = x.
Et au moment du pop, si la pile contient quelque chose de moins que la minValue, c'est notre déclencheur pour mettre à jour le minVAlue. Nous devons calculer prevMinValue à partir de curMinValue et y. y = 2 * curMinValue - prevMinValue [Prouvé] prevMinVAlue = 2 * curMinvalue - y.
2 * curMinValue - y est le nombre que nous devons mettre à jour maintenant vers prevMinValue.
Le code pour la même logique est partagé ci-dessous avec la complexité du temps O (1) et de l'espace O (1).
la source
Voici ma version d'implémentation.
la source
la source
J'ai trouvé cette solution ici
la source
la source
la source
la source
Voici mon code qui fonctionne avec O (1). Ici, j'ai utilisé une paire de vecteurs qui contient la valeur qui a poussé et contient également la valeur minimale jusqu'à cette valeur poussée.
Voici ma version de l'implémentation C ++.
la source
la source
Class
-MinStack
? La documentation Java d'Oracle conseille d'utiliserDeque
.Une implémentation pratique pour trouver le minimum dans une pile d'objets conçus par l'utilisateur, nommée: École
La pile va stocker les écoles dans la pile en fonction du rang attribué à une école dans une région spécifique, par exemple, findMin () donne l'école où nous obtenons le nombre maximal de demandes d'admission, qui à son tour doit être défini par le comparateur qui utilise le rang associé aux écoles de la saison précédente.
L'objet école est également le suivant:
Cet exemple couvre les éléments suivants: 1. Implémentation de la pile pour les objets définis par l'utilisateur, ici, école 2. Implémentation de la méthode hashcode () et equals () en utilisant tous les champs d'objets à comparer 3. Une implémentation pratique pour le scénario où nous rqeuire pour que l'opération Stack contains soit dans l'ordre O (1)
la source
language-agnostic
veuillez spécifier ce que vous utilisez pour le code (et supprimez les espaces avantThe Code for same is below:
.) Comment cela prend-il en chargestack.pop()
? (etpush()
?)Voici l'implémentation PHP de ce qui a été expliqué dans la réponse de Jon Skeet comme l'implémentation légèrement meilleure de la complexité de l'espace pour obtenir le maximum de pile dans O (1).
la source
Voici l'implémentation C ++ de Jon Skeets Answer . Ce n'est peut-être pas le moyen le plus optimal de le mettre en œuvre, mais il fait exactement ce qu'il est censé faire.
Et voici le pilote de la classe
Production:
la source
Nous pouvons le faire en temps O (n) et en complexité spatiale O (1), comme ceci:
la source
Je pense que vous pouvez simplement utiliser une LinkedList dans votre implémentation de pile.
La première fois que vous transmettez une valeur, vous mettez cette valeur en tête de liste liée.
puis chaque fois que vous poussez une valeur, si la nouvelle valeur <head.data, effectuez une opération prepand (ce qui signifie que la tête devient la nouvelle valeur)
sinon, effectuez une opération d'ajout.
Quand vous faites un pop (), vous vérifiez si min == linkedlist.head.data, si oui, alors head = head.next;
Voici mon code.
la source
la source
la source
J'ai vu une solution brillante ici: https://www.geeksforgeeks.org/design-a-stack-that-supports-getmin-in-o1-time-and-o1-extra-space/
Ci-dessous est le code python que j'ai écrit en suivant l'algorithme:
la source
Pour obtenir des éléments Min de Stack. Nous devons utiliser Two stack .ie Stack s1 et Stack s2.
--------------------- Appel récursif des étapes 2 à 4 -----------------------
if Nouvel élément ajouté à la pile s1.Ensuite, pop éléments de la pile s2
comparer les nouveaux éléments avec s2. lequel est le plus petit, appuyez sur s2.
pop de la pile s2 (qui contient l'élément min)
Le code ressemble à:
la source
Je pense que seule l'opération push souffre, c'est assez. Mon implémentation comprend une pile de nœuds. Chaque nœud contient l'élément de données et aussi le minimum à ce moment. Ce minimum est mis à jour à chaque fois qu'une opération push est effectuée.
Voici quelques points pour comprendre:
J'ai implémenté la pile en utilisant la liste liée.
Un pointeur en haut pointe toujours vers le dernier élément poussé. Lorsqu'il n'y a aucun élément dans cette pile, le haut de la pile est NULL.
Lorsqu'un élément est poussé, un nouveau nœud est alloué qui a un pointeur suivant qui pointe vers la pile précédente et top est mis à jour pour pointer vers ce nouveau nœud.
La seule différence avec l'implémentation normale de la pile est que pendant l'envoi, il met à jour un membre min pour le nouveau nœud.
Veuillez jeter un œil au code implémenté en C ++ à des fins de démonstration.
Et la sortie du programme ressemble à ceci:
la source
la source