EDIT: Isso falha na restrição de "espaço constante" - basicamente dobra o espaço necessário. Eu duvido muito que haja uma solução que não faça isso, sem destruir a complexidade do tempo de execução em algum lugar (por exemplo, fazer push / pop O (n)). Observe que isso não muda a complexidade do espaço necessário, por exemplo, se você tem uma pilha com O (n) requisitos de espaço, ainda será O (n) apenas com um fator constante diferente.
Solução de espaço não constante
Mantenha uma pilha "duplicada" de "mínimo de todos os valores mais baixos na pilha". Quando você abre a pilha principal, abre a pilha mínima também. Quando você empurra a pilha principal, empurra o novo elemento ou o mínimo atual, o que for menor. getMinimum()
é então implementado como justo minStack.peek()
.
Então, usando seu exemplo, teríamos:
Real stack Min stack
5 --> TOP 1
1 1
4 2
6 2
2 2
Depois de estourar duas vezes, você obtém:
Real stack Min stack
4 2
6 2
2 2
Informe-me se esta informação não for suficiente. É simples quando você groca, mas pode exigir um pouco de coçar a cabeça no início :)
(A desvantagem, claro, é que ele dobra a necessidade de espaço. O tempo de execução não sofre significativamente - ou seja, ainda tem a mesma complexidade.)
EDITAR: Há uma variação que é um pouco mais complicada, mas tem um espaço melhor em geral. Ainda temos a pilha mínima, mas só saímos dela quando o valor que retiramos da pilha principal é igual ao da pilha mínima. Só fazemos push para a pilha mínima quando o valor que está sendo colocado na pilha principal é menor ou igual ao valor mínimo atual. Isso permite valores mínimos duplicados. getMinimum()
ainda é apenas uma operação de espiada. Por exemplo, pegando a versão original e pressionando 1 novamente, obteríamos:
Real stack Min stack
1 --> TOP 1
5 1
1 2
4
6
2
Popping do acima aparece de ambas as pilhas porque 1 == 1, deixando:
Real stack Min stack
5 --> TOP 1
1 2
4
6
2
Popping novamente só sai da pilha principal, porque 5> 1:
Real stack Min stack
1 1
4 2
6
2
Estourar novamente abre ambas as pilhas porque 1 == 1:
Real stack Min stack
4 2
6
2
Isso acaba com a mesma complexidade de espaço do pior caso (o dobro da pilha original), mas um uso de espaço muito melhor se raramente obtivermos um "novo mínimo ou igual".
EDIT: Aqui está uma implementação do esquema maligno de Pete. Não testei completamente, mas acho que está tudo bem :)
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;
}
}
Adicione um campo para conter o valor mínimo e atualize-o durante Pop () e Push (). Dessa forma getMinimum () será O (1), mas Pop () e Push () terão que fazer um pouco mais de trabalho.
Se o valor mínimo for exibido, Pop () será O (n), caso contrário, eles ainda serão O (1). Ao redimensionar, Push () torna-se O (n) de acordo com a implementação de Stack.
Aqui está uma implementação rápida
fonte
Ele armazena o mínimo atual explicitamente e se o mínimo mudar, em vez de empurrar o valor, ele empurra um valor com a mesma diferença do outro lado do novo mínimo (se min = 7 e você empurra 5, empurra 3 em vez disso (5- | 7-5 | = 3) e define min como 5; se você estourar 3 quando min for 5, verá que o valor estourado é menor que min, então inverte o procedimento para obter 7 para o novo min e, em seguida, retorna o anterior min). Como qualquer valor que não altera o mínimo atual é maior do que o mínimo atual, você tem algo que pode ser usado para diferenciar entre os valores que alteram o mínimo e os que não.
Em linguagens que usam números inteiros de tamanho fixo, você está pegando emprestado um pouco de espaço da representação dos valores, então pode haver um estouro negativo e a declaração falhará. Mas, caso contrário, é espaço extra constante e todas as operações ainda são O (1).
As pilhas que são baseadas em listas vinculadas têm outros lugares dos quais você pode pegar emprestado um pouco, por exemplo, em C, o bit menos significativo do próximo ponteiro, ou em Java, o tipo dos objetos na lista vinculada. Para Java, isso significa que há mais espaço usado em comparação com uma pilha contígua, pois você tem a sobrecarga do objeto por link:
Em C, a sobrecarga não está lá, e você pode pegar emprestado o lsb do próximo ponteiro:
No entanto, nenhum deles é verdadeiramente O (1). Eles não requerem mais espaço na prática, porque exploram buracos nas representações de números, objetos ou ponteiros nessas linguagens. Mas uma máquina teórica que usasse uma representação mais compacta exigiria um bit extra a ser adicionado a essa representação em cada caso.
fonte
pop()
se o último valor enviado foiInteger.MIN_VALUE
(por exemplo, push 1, push Integer.MIN_VALUE, pop). Isso se deve ao underflow mencionado acima. Caso contrário, funciona para todos os valores inteiros.Encontrei uma solução que satisfaz todas as restrições mencionadas (operações de tempo constante) e espaço extra constante .
A ideia é armazenar a diferença entre o valor mínimo e o número de entrada e atualizar o valor mínimo se ele não for mais o mínimo.
O código é o seguinte:
O crédito vai para: https://leetcode.com/discuss/15679/share-my-java-solution-with-only-one-stack
fonte
Bem, quais são as restrições de tempo de execução de
push
epop
? Se não for necessário que sejam constantes, basta calcular o valor mínimo nessas duas operações (tornando-as O ( n )). Caso contrário, não vejo como isso pode ser feito com espaço adicional constante.fonte
Aqui está meu código que roda com O (1). O código anterior que postei teve problema quando o elemento mínimo é exibido. Eu modifiquei meu código. Este usa outro Stack que mantém o elemento mínimo presente na pilha acima do elemento empurrado atual.
fonte
Usei um tipo diferente de pilha. Aqui está a implementação.
Resultado:
Tente. Acho que responde à pergunta. O segundo elemento de cada par fornece o valor mínimo visto quando aquele elemento foi inserido.
fonte
Estou postando o código completo aqui para encontrar o mínimo e o máximo em uma determinada pilha.
A complexidade do tempo será O (1) ..
Deixe-me saber se você está enfrentando algum problema
Obrigado, Vikash
fonte
Você poderia estender sua classe de pilha original e apenas adicionar o rastreamento mínimo a ela. Deixe a classe pai original lidar com todo o resto como de costume.
fonte
Aqui está minha solução em java usando a lista de gostos.
}
fonte
Vamos supor que a pilha na qual estaremos trabalhando seja esta:
Na representação acima, a pilha é construída apenas pelo valor à esquerda e o valor à direita [minvalue] é escrito apenas para fins de ilustração, o qual será armazenado em uma variável.
O problema real é quando o valor que é o valor mínimo é removido naquele ponto, como podemos saber qual é o próximo elemento mínimo sem iterar na pilha.
Como, por exemplo, em nossa pilha, quando 6 get's aparecem, sabemos disso, este não é o elemento mínimo porque o elemento mínimo é 2, portanto, podemos removê-lo com segurança sem atualizar nosso valor mínimo.
Mas quando estouramos 2, podemos ver que o valor mínimo é 2 agora e se esse get aparecer, precisamos atualizar o valor mínimo para 3.
Ponto 1:
Agora, se você observar cuidadosamente, precisamos gerar minvalue = 3 a partir deste estado particular [2, minvalue = 2]. ou se você for depperin a pilha, precisamos gerar minvalue = 7 a partir deste estado particular [3, minvalue = 3] ou se você for mais depperin na pilha, precisamos gerar minvalue = 8 a partir deste estado particular [7, minvalue = 7]
Você notou algo em comum em todos os 3 casos acima, o valor que precisamos gerar depende de duas variáveis que são iguais. Corrigir. Por que isso está acontecendo porque quando colocamos algum elemento menor que o minvalue atual, basicamente colocamos esse elemento na pilha e atualizamos o mesmo número em minvalue também.
Ponto 2:
Portanto, estamos basicamente armazenando duplicatas do mesmo número uma vez na pilha e uma vez na variável minvalue. Precisamos nos concentrar em evitar essa duplicação e armazenar dados úteis na pilha ou no minvalue para gerar o mínimo anterior, conforme mostrado nos CASES acima.
Vamos nos concentrar no que devemos armazenar na pilha quando o valor a ser armazenado no push é menor que o valor mínimo. Vamos chamar esta variável de y, então agora nossa pilha será parecida com isto:
Eu os renomeei como y1, y2, y3 para evitar a confusão de que todos eles terão o mesmo valor.
Ponto 3:
Agora, vamos tentar encontrar algumas restrições sobre y1, y2 e y3. Você se lembra quando exatamente precisamos atualizar o minvalue ao fazer pop (), apenas quando tivermos exibido o elemento que é igual ao minvalue. Se exibirmos algo maior do que minvalue, não precisamos atualizar minvalue. Portanto, para acionar a atualização do minvalue, y1, y2 e y3 devem ser menores do que o minvalue correspondente. [Estamos avodando a igualdade para evitar duplicidade [Point2]], então a restrição é [y <minValue].
Agora vamos voltar para preencher y, precisamos gerar algum valor e colocar y no momento do push, lembre-se. Vamos pegar o valor que está chegando para push ser x, que é menor que prevMinvalue, e o valor que realmente colocaremos na pilha como y. Portanto, uma coisa é óbvia que newMinValue = x, ey <newMinvalue.
Agora precisamos calcular y (lembre-se de que y pode ser qualquer número menor que newMinValue (x), portanto, precisamos encontrar algum número que possa cumprir nossa restrição) com a ajuda de prevMinvalue e x (newMinvalue).
Portanto, no momento de pressionar x, se for menor que prevMinvalue, então pressionamos y [2 * x-prevMinValue] e atualizamos newMinValue = x.
E no momento do pop, se a pilha contiver algo menor do que minValue, esse é nosso gatilho para atualizar o minVAlue. Temos que calcular prevMinValue a partir de curMinValue e y. y = 2 * curMinValue - prevMinValue [Provado] prevMinVAlue = 2 * curMinvalue - y.
2 * curMinValue - y é o número que precisamos atualizar agora para prevMinValue.
O código para a mesma lógica é compartilhado abaixo com tempo O (1) e complexidade de espaço O (1).
fonte
Aqui está minha versão de implementação.
fonte
fonte
Eu encontrei esta solução aqui
fonte
fonte
fonte
fonte
Aqui está meu código que roda com O (1). Aqui eu usei o par de vetores que contém o valor que empurrou e também contém o valor mínimo até este valor empurrado.
Aqui está minha versão da implementação C ++.
fonte
fonte
Class
-MinStack
? A documentação Java da Oracle aconselha o usoDeque
.Uma implementação prática para encontrar o mínimo em uma pilha de objetos projetados pelo usuário, chamada: Escola
A Pilha vai armazenar as Escolas na Pilha com base na classificação atribuída a uma escola em uma região específica, digamos, findMin () dá a Escola onde obtemos o número máximo de inscrições para admissões, que por sua vez, deve ser definido pelo comparador que usa a classificação associada às escolas na temporada anterior.
Além disso, o Objeto da Escola é o seguinte:
Este exemplo cobre o seguinte: 1. Implementação de Stack para objetos definidos pelo usuário, aqui, School 2. Implementação para o método hashcode () e equals () usando todos os campos de objetos a serem comparados 3. Uma implementação prática para o cenário onde nós rqeuire para fazer com que a operação da pilha esteja na ordem de O (1)
fonte
language-agnostic
especifique o que você usa para o código (e remova os espaços em branco antesThe Code for same is below:
). Como isso é compatívelstack.pop()
? (epush()
?)Aqui está a implementação de PHP do que foi explicado na resposta de Jon Skeet como a implementação de complexidade de espaço um pouco melhor para obter o máximo de pilha em O (1).
fonte
Aqui está a implementação C ++ da Resposta de Jon Skeets . Pode não ser a maneira mais ideal de implementá-lo, mas faz exatamente o que deveria.
E aqui está o motorista da aula
Resultado:
fonte
Nós podemos fazer isso em O (n) e O (1) a complexidade do espaço, assim:
fonte
Acho que você pode simplesmente usar um LinkedList em sua implementação de pilha.
Na primeira vez que você envia um valor, você o coloca como o cabeçalho da lista vinculada.
então, cada vez que você enviar um valor, se o novo valor for <head.data, faça uma operação prepand (o que significa que o head se torna o novo valor)
caso contrário, faça uma operação de acréscimo.
Quando você faz um pop (), verifica se min == linkedlist.head.data, se sim, então head = head.next;
Aqui está meu código.
fonte
fonte
fonte
Encontrei uma solução brilhante aqui: https://www.geeksforgeeks.org/design-a-stack-that-supports-getmin-in-o1-time-and-o1-extra-space/
Abaixo está o código Python que escrevi seguindo o algoritmo:
fonte
Para obterMin elementos de Stack. Temos que usar Duas pilhas, ou seja, Pilha s1 e Pilha s2.
--------------------- Chame recursivamente as etapas 2 a 4 -----------------------
se Novo elemento adicionado à pilha s1. Em seguida, pop os elementos da pilha s2
compare novos elments com s2. qual for menor, empurre para s2.
pop da pilha s2 (que contém o elemento min)
O código se parece com:
fonte
Acho que só a operação push sofre, é o suficiente. Minha implementação inclui uma pilha de nós. Cada nó contém o item de dados e também o mínimo naquele momento. Este mínimo é atualizado cada vez que uma operação push é realizada.
Aqui estão alguns pontos para compreensão:
Implementei a pilha usando a lista vinculada.
Um ponteiro superior sempre aponta para o último item empurrado. Quando não há nenhum item na pilha, o topo é NULL.
Quando um item é empurrado, um novo nó é alocado, o qual possui um próximo ponteiro que aponta para a pilha anterior e o topo é atualizado para apontar para este novo nó.
A única diferença com a implementação normal da pilha é que, durante o push, ele atualiza um membro min para o novo nó.
Por favor, dê uma olhada no código que é implementado em C ++ para fins de demonstração.
E a saída do programa é assim:
fonte
fonte