貪欲で 最後の マスまでの 最少の 跳ぶ回数を求める
すごろくの
海外で定番の問題リスト 4 本には入っていません
問題
すごろくのi からは 1 歩以上 steps[i] 歩以下のlen(steps) - 1) に
- どの
入力でも、 最後の マスには 必ず着けます - 後ろへ
戻る ことは できません - マスが 1 つだけなら、
最初から 着いているので 答えは 0 です stepsの長さは 1 以上 100000 以下、 値は どれも 0 以上 1000 以下です
入力と出力の例
例 1
マス 0 から 1 歩で
例 2
マスが 1 つだけなので、
例 3
マス 0 から 5 歩で、
面接での聞かれ方
面接では、
- 「必ず
最後まで 行けるとして、 最少で 何回跳べば よいですか」 - 最初に
動的計画法や 幅優先探索で 書き、 「記憶を O(1) に できますか」と 聞かれて 貪欲に 直す流れもあります - 「着けない
入力が 来たら どうしますか」と、 前提を 聞かれる こともあります
必ず
ヒント
まだ開いていません
付箋は 3 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3答えに近い
アルゴリズムのチートシートの「配列と文字列」に、
関わる学び
配列と
まず 考える手順
段 1
素直にsteps[i] 個の
段 2
幅優先探索のsteps[0] まで、というように、
段 3
いまのend と、far をfar をend にend を far にします。
解答
Python
Python
def min_jumps(steps):
jumps = 0
end = 0
far = 0
for i in range(len(steps) - 1):
far = max(far, i + steps[i])
if i == end:
jumps += 1
end = far
return jumpsJavaScript
JavaScript
function minJumps(steps) {
let jumps = 0;
let end = 0;
let far = 0;
const n = steps.length;
for (let i = 0; i < n - 1; i++) {
far = Math.max(
far, i + steps[i],
);
if (i === end) {
jumps++;
end = far;
}
}
return jumps;
}Go
Go
func minJumps(steps []int) int {
jumps, end, far := 0, 0, 0
n := len(steps)
for i := 0; i < n-1; i++ {
far = max(far, i+steps[i])
if i == end {
jumps++
end = far
}
}
return jumps
}end がi が end に
計算量
- 時間は O(n) です。
マスを 前から 1 回なめ、 1 マスごとの 手間は一定です - 使う
記憶は O(1) です。 持つのは 回数と endとfarだけです - 幅優先探索で
待ち行列を 使う 書き方でも 答えは 同じですが、 記憶が O(n) 要ります
よく ある間違い
- 最後の
マスまで ループを回す。 range(len(steps))と書くと、 最後の マスに 着いた所で i == endになった とき、 要らない 1 回を 足すことがあります。 例 2 の [0]では 1 を返してしまいます - いつも
最大の 歩数で跳ぶ。 例 1 で マス 0 から 最大の 2 歩で マス 2 へ 跳ぶと、 そこから 届くのは マス 3 までで、 遠回りに なります。 1 本の 道を 選ぶのではなく、 範囲で考えます - 跳ぶたびに
最も 遠い マスへ 移ったと 考えて、 次の マスを farから始める。 範囲の中の 手前の マスから、 もっと 遠く へ届く ことがあります。 範囲の 中の マスは 全部見て farを広げます farを広げる 前に 回数を足す。 i == endの確かめを farの更新より 先に すると、 マス end自身から届く 先が endに入りません。 例 1 では 最初の 回で endが 0 のまま残り、 その あと 広がらないので 1 を返します
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「k 回で
着ける マスは ひと 続きの 範囲に なり、 次の 範囲の 右端は、 いまの 範囲の 中の マスから 届く 最も 遠い マスです。 いまの 範囲の 右端と、 次に 届く 最も 遠い マスを 持って前から 見て、 右端に 来たら 回数を 1 足して 範囲を 広げます。 最後の マスからは 跳ばないので、 見るのは その 手前までです。 時間は O(n)、 記憶は O(1) です。」
書き終えたら、
「例 1 で
たどります。 マス 0 で 届く 最も 遠い マスは 2、 右端 0 に 来たので 1 回目、 右端は 2 です。 マス 1 で 最も 遠いのは 5、 マス 2 でも 5 のままで、 右端 2 に 来たので 2 回目、 右端は 5 です。 マス 3 と 4 では 5 のまま、 マス 5 で 8 に なり、 右端 5 に 来たので 3 回目、 右端は 8 です。 マス 6 では 増えず、 答えは 3 です。」