Est-ce que quelqu'un peut me dire quelle structure de données supporte les opérations d'insertion/suppression/maximum dans O (1)
Ceci est une question d'entrevue classique, et est généralement présenté comme suit:
Concevez une structure de données de type pile qui effectue les opérations Push, Pop et Min (ou Max) en O(1). Il n'y a pas de contraintes d'espace.
La réponse est que vous utilisez deux piles: la pile principale et une pile min (ou max).
Ainsi, par exemple, après avoir placé 1,2,3,4,5 sur la pile, vos piles ressembleraient à ceci:
MAIN MIN
+---+ +---+
| 5 | | 1 |
| 4 | | 1 |
| 3 | | 1 |
| 2 | | 1 |
| 1 | | 1 |
+---+ +---+
Cependant, si vous deviez pousser 5,4,3,2,1, les piles ressembleraient à ceci:
MAIN MIN
+---+ +---+
| 1 | | 1 |
| 2 | | 2 |
| 3 | | 3 |
| 4 | | 4 |
| 5 | | 5 |
+---+ +---+
Pour 5,2,4,3,1 vous auriez:
MAIN MIN
+---+ +---+
| 1 | | 1 |
| 3 | | 2 |
| 4 | | 2 |
| 2 | | 2 |
| 5 | | 5 |
+---+ +---+
etc.
Vous pouvez également économiser de l'espace en accédant à la pile min. Uniquement lorsque l'élément minimum change, à condition que les éléments soient distincts.
La solution suivante utilise O(1) plus de mémoire et le temps O(1) pour les opérations max, Push et pop. Gardez une variable max qui gardera trace de l’élément max actuel à un moment donné. Utilisons le fait que quand max est mis à jour, tous les éléments de la pile doivent être inférieurs au nouvel élément max. Quand une opération Push se produit et que le nouvel élément (newElement) est supérieur au maximum actuel, nous poussons le max + newElement dans la pile et mettons à jour max = newElement.
Lorsque nous effectuons une opération pop et que nous constatons que l'élément popped actuel est supérieur au max actuel, nous savons qu'il s'agit de l'endroit où nous avions mis à jour notre pile pour qu'elle contienne max + elem. Donc, l'élément à renvoyer est max et max = poppedElem - max.
Pour par exemple. si nous poussons 1, 2, 3, 4, 5, les variables stack et max ressembleront à celles ci-dessous:
MAIN Value of MAX
+---+ +---+
| 9 | max = | 5 |
| 7 | max = | 4 |
| 5 | max = | 3 |
| 3 | max = | 2 |
| 1 | max = | 1 |
+---+ +---+
Maintenant, disons que nous sautons un élément, nous allons fondamentalement pop, élément max (depuis top> max) et mettre à jour l'élément max sur (top-max)
MAIN Value of MAX
+---+ +---+
| 7 | max = | 4 | = (9-5)
| 5 | max = | 3 |
| 3 | max = | 2 |
| 1 | max = | 1 |
+---+ +---+
Maintenant, disons que nous poussons les nombres 5, 4, 3, 2, 1, la pile ressemblera à ceci:
MAIN Value of MAX
+---+ +---+
| 1 | max = | 5 |
| 2 | max = | 5 |
| 3 | max = | 5 |
| 4 | max = | 5 |
| 5 | max = | 5 |
+---+ +---+
Lorsque nous sautons, le haut de la pile est sauté puisque top <max, et max reste inchangé.
Vous trouverez ci-dessous un pseudo-code pour chacune des opérations pour une meilleure compréhension.
Elem max;
void Push(Elem x){
if x < max :
Push(x);
else{
Push(x+max);
max = x;
}
}
Elem Pop(){
Elem p = pop();
if |p| < |max|:
return p;
else{
max = p - max;
return max;
}
}
Elem Max(){
return max;
}
Push et Pop sont des opérations de pile normales. J'espère que cela t'aides.
Le commentaire de @ KennyTM souligne un détail manquant important - insérer où et supprimer de où. Je vais donc supposer que vous voulez toujours insérer et supprimer uniquement à partir d'une extrémité, comme une pile.
Insertion (Push) et Supprimer (pop) sont O (1).
Pour obtenir Max dans O (1), utilisez une pile supplémentaire pour enregistrer le maximum actuel, qui correspond à la pile principale.
Si vous utilisez uniquement des comparaisons, vous aurez beaucoup de mal à trouver une telle structure de données.
Par exemple, vous pouvez insérer n éléments, obtenir max, supprimer max, etc. et trier les nombres dans le temps O(n), tandis que la limite inférieure théorique est Omega (nlogn).
Le programme ci-dessous garde la trace du nombre maximal d'éléments dans la pile de manière à ce que le pointeur supérieur nous indique le maximum dans la pile: Donc, max serait O (1), et nous pourrions trouver max par max. [N]
ITEM MAX
+---+ +---+
| 1 | | 1 |
| 10| | 10|
| 9 | | 10|
| 19| | 19| <--top
+---+ +---+
Programme Java:
public class StackWithMax {
private int[] item;
private int N = 0;
private int[] max;
public StackWithMax(int capacity){
item = new int[capacity];//generic array creation not allowed
max = new int[capacity];
}
public void Push(int item){
this.item[N++] = item;
if(max[N-1] > item) {
max[N] = max[N-1];
} else {
max[N] = item;
}
}
public void pop() {
this.item[N] = 0;
this.max[N] = 0;
N--;
}
public int findMax(){
return this.max[N];
}
public static void main(String[] args) {
StackWithMax max = new StackWithMax(10);
max.Push(1);
max.Push(10);
max.Push(9);
max.Push(19);
System.out.println(max.findMax());
max.pop();
System.out.println(max.findMax());
}
}
Comme certains l'ont déjà souligné, la question manque d'informations. Vous ne spécifiez pas d'insérer/supprimer, ni la nature des données que nous traitons.
Quelques idées qui pourraient être utiles: Vous dites,
opération d'insertion/suppression/maximum en O (1)
notez que si nous pouvons insérer, supprimer et trouver maximun dans O (1), nous pouvons utiliser cette technique hipotétique pour trier O (n), car nous pouvons insérer les n éléments, puis prendre max/delete et nous obtenons tous triés. Il est prouvé qu’aucun algorithme de tri basé sur des comparaisons ne peut trier moins que O (nlogn), nous savons donc qu’aucune approche basée sur la comparaison ne fonctionnera. En fait, l'un des moyens les plus rapides connus est la file d'attente Brodal, mais son temps de suppression est supérieur à O (1).
Peut-être que la solution est quelque chose comme un arbre de base, où la complexité de toutes ces opérations est liée à la longueur de la clé par rapport à la quantité de clés. Cela n’est valable que s’ils vous permettent de lier la longueur de la clé à un autre chiffre afin que vous puissiez la considérer comme constante.
Mais peut-être que ce n'était pas quelque chose d'aussi générique. Une autre interprétation est que les insert/delete sont ceux d'une pile classique. Dans ce cas restreint, vous pouvez utiliser la solution à double pile que Berk Güder vous a donnée.