編集:これは「一定のスペース」制約に失敗します-基本的に必要なスペースが2倍になります。ランタイムの複雑さをどこかで壊さずに(たとえば、プッシュ/ポップO(n)を作成する)、それを行わないソリューションがあるかどうかは非常に疑わしいです。これによって必要なスペースの複雑さが変わることはないことに注意してください。たとえば、O(n)のスペース要件を持つスタックがある場合でも、定数係数が異なるだけでO(n)になります。
非定空間ソリューション
「スタックの下位にあるすべての値の最小値」の「重複」スタックを保持します。メインスタックをポップするときは、最小スタックもポップします。メインスタックをプッシュするときは、新しい要素または現在の最小値のいずれか低い方をプッシュします。getMinimum()
次に、として実装されますminStack.peek()
。
したがって、あなたの例を使用すると、次のようになります。
Real stack Min stack
5 --> TOP 1
1 1
4 2
6 2
2 2
2回ポップすると、次のようになります。
Real stack Min stack
4 2
6 2
2 2
十分な情報がない場合はお知らせください。簡単に理解できますが、最初は少し頭を悩ませる必要があるかもしれません:)
(もちろん、欠点は、必要なスペースが2倍になることです。ただし、実行時間に大きな影響はありません。つまり、同じ複雑さです。)
編集:少し厄介なバリエーションがありますが、一般的にはより良いスペースがあります。最小スタックはまだありますが、メインスタックからポップする値が最小スタックの値と等しい場合にのみ、最小スタックからポップします。メインスタックにプッシュされる値が現在の最小値以下の場合にのみ、最小スタックにプッシュします。これにより、最小値を複製できます。まだただのぞき見操作です。たとえば、元のバージョンを取得して1をもう一度押すと、次のようになります。getMinimum()
Real stack Min stack
1 --> TOP 1
5 1
1 2
4
6
2
上記からポップすると、1 == 1であるため、両方のスタックからポップします。
Real stack Min stack
5 --> TOP 1
1 2
4
6
2
5> 1であるため、再度ポップするとメインスタックからのみポップされます。
Real stack Min stack
1 1
4 2
6
2
1 == 1であるため、再度ポップすると両方のスタックがポップされます。
Real stack Min stack
4 2
6
2
これは、同じ最悪の場合のスペースの複雑さ(元のスタックの2倍)になりますが、「新しい最小値または等しい」がめったに得られない場合は、スペースの使用量がはるかに良くなります。
編集:これはピートの邪悪な計画の実装です。徹底的にテストしていませんが、大丈夫だと思います:)
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;
}
}