問題
整数をMinStack として
push(x)は、整数 xをいちばん上に 積みます。 何も 返しません pop()は、いちばん上の 値を 取り 除きます。 何も 返しません top()は、いちばん上の 値を 返します。 取り 除きはしません getMin()は、いま入っている 値の うち、 いちばん 小さい 値を返します
メソッドのget_min のようにPush、Pop、Top、GetMin とnewMinStack() で
入力は、ops と、args でops のargs のpush、pop は null です。
pop、top、getMinは、スタックが 空でない ときだけ呼びます xは -2147483648 以上 2147483647 以下です- 操作の
回数は 30000 回以下です
入力と出力の例
例 1
5、
入力
ops = ["MinStack", "push",
"push", "push", "getMin",
"pop", "getMin", "pop",
"getMin", "top"]
args = [[], [5], [3], [8],
[], [], [], [], [], []]出力
[null, null, null, null, 3,
null, 3, null, 5, 5]例 2
いちばん
入力
ops = ["MinStack", "push",
"push", "getMin", "pop",
"getMin", "top"]
args = [[], [2], [2], [],
[], [], []]出力
[null, null, null, 2, null,
2, 2]例 3
負の
入力
ops = ["MinStack", "push",
"push", "top", "getMin",
"push", "pop", "pop",
"getMin"]
args = [[], [-1], [-6], [],
[], [0], [], [], []]出力
[null, null, null, -6, -6,
null, null, null, -1]面接での聞かれ方
面接では、
- 「いちばん
小さい 値を、 毎回 全部見ずに 返してください」と、 O(1) が 条件に入ります - 最小値を 1 つの
置き場だけで 持つ 書き方を 出すと、 「その値を 取り除いたら、 次の 最小値は どうやって 知りますか?」と 聞かれます - 書き終えた
あとに 「記憶を もっと 減らせますか?」 「同じ 値が 何度も 積まれたら どうなりますか?」と続きます
最小値は、
アルゴリズムのチートシートの「ハッシュマップ」に、この型の要点を表とコードでまとめています。
まず 考える手順
段 1
まずはgetMin がgetMin が O(n) に
段 2
最小値を 1 つの
段 3
スタックはvals とmins をmins のmins に
段 4
取り除くvals と mins のmins のtop は vals のgetMin は mins の
解答
Python
Python
class MinStack:
def __init__(self):
self.vals = []
self.mins = []
def push(self, x):
mins = self.mins
m = x
if mins:
m = min(m, mins[-1])
self.vals.append(x)
mins.append(m)
def pop(self):
self.vals.pop()
self.mins.pop()
def top(self):
return self.vals[-1]
def get_min(self):
return self.mins[-1]JavaScript
JavaScript
class MinStack {
constructor() {
this.vals = [];
this.mins = [];
}
push(x) {
const mins = this.mins;
const n = mins.length;
let m = x;
if (n > 0) {
const last = mins[n - 1];
m = Math.min(m, last);
}
this.vals.push(x);
mins.push(m);
}
pop() {
this.vals.pop();
this.mins.pop();
}
top() {
return this.vals.at(-1);
}
getMin() {
return this.mins.at(-1);
}
}Go
Go
type MinStack struct {
vals []int
mins []int
}
func newMinStack() *MinStack {
return &MinStack{}
}
func (s *MinStack) Push(x int) {
m := x
if n := len(s.mins); n > 0 {
m = min(m, s.mins[n-1])
}
s.vals = append(s.vals, x)
s.mins = append(s.mins, m)
}
func (s *MinStack) Pop() {
n := len(s.vals) - 1
s.vals = s.vals[:n]
s.mins = s.mins[:n]
}
func (s *MinStack) Top() int {
return s.vals[len(s.vals)-1]
}
func (s *MinStack) GetMin(
) int {
return s.mins[len(s.mins)-1]
}vals と mins はpop はreturn していないので、None にmin は、
計算量
- 時間は、
4 つの 操作の どれも O(1) です。 並びの 末尾に 足すか、 末尾を 取り除くか、 末尾を 見るだけです - 使う
記憶は、 積んでいる 値の 数を n として O(n) です。 valsとminsで 2 倍持ちます minsには「いまの 最小値以下の 値が 積まれた ときだけ」 積み、 取り除く 値が minsの上と 同じ ときだけ minsからも取り除くと、 値が ばらばらに 積まれる 場合の 記憶を 減らせます。 その ときも 時間は O(1) のままです
よく ある間違い
- 最小値を 1 つの
置き場だけで持つ。 いちばん 小さい 値を 取り除いた後、 次に 小さい 値が 分から なくなります。 例 1 で 3 を 取り除いた後、 5 を 返せません - 記憶を
減らす 書き方で、 「より小さい」 ときだけ minsに積む。 同じ最小値が 2 回積まれた とき、 minsには 1 回しか入りません。 例 2 で 2 を 1 つ取り除くと minsが空に なり、 残っている 2 を 返せません。 「以下」の ときに積みます - 空の
ときに minsの上を読む。 最初の pushでmins[-1]やmins[n - 1]を読むと、 Python は 並びの 外の 読み出しで 止まり、 JavaScript は undefinedと比べて NaNを積みます。 空か どうかを 先に見ます
解答を動かした版 Python 3.12.14Node.js 22.23.4Go 1.24.6確認日 2026年10月30日
面接での 話し方の例
書き始める
「スタックは
上から しか 取り除かないので、 ある 高さまでの 最小値は、 その上に 何が 積まれても 変わりません。 値の 並びと 並べて、 その 高さまでの 最小値の 並びを 持ち、 積むときは 新しい 値といまの 最小値の 小さい ほうを 積みます。 取り除く ときは 両方から 1 つずつです。 4 つの 操作は どれも O(1)、 記憶は O(n) です。」
書き終えたら、
「例 1 で
たどります。 5、 3、 8 と 積むと、 値の 並びは [5, 3, 8]、最小値の 並びは [5, 3, 3]です。getMinは 3 です。1 つ取り除くと [5, 3]と[5, 3]で、まだ 3 です。 もう 1 つ取り除くと [5]と[5]になり、 getMinもtopも 5 です。」
