二分探索で 回された 並びの いちばん 小さい値を探す
小さい
海外で定番の問題リスト 4 本には入っていません
問題
整数のnums をnums は、
- たとえば
[3, 8, 12, 20, 25]を 12 の前で 切って 回すと [12, 20, 25, 3, 8]になります。 切らずに そのままの こともあります - 同じ値は 2 回出てきません
- 要素の
数は 1 以上 5000 以下、 値は どれも -5000 以上 5000 以下です - 時間は O(log n) で
解いてください
入力と出力の例
例 1
13 の
例 2
一度も
例 3
いちばん
面接での聞かれ方
二分探索で
- 「回された
並びの 最小値を、 全部を 見ずに 求めてください」 - 回された
並びから 値を 探す問題 (この 一覧の rotated-array-search) の 前置きとして 出される ことも、 続きとして 聞かれる こともあります。 最小値の 位置が 分かれば、 切れ目の 左右どちらかで ふつうの 二分探索ができます - 「同じ値が
あっても よいとしたら どうなりますか?」と 続けて 聞かれる ことがあります。 まん中と 右端が 同じだと 向きが 決まらず、 右端を 1 つ 縮めるしかないので、 いちばん悪いと O(n) になります
ミドルの
ヒント
まだ開いていません
付箋は 4 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3
ヒント 4答えに近い
アルゴリズムのチートシートの「ソートと二分探索」に、
関わる学び
二分探索は、
まず 考える手順
段 1
まずは
段 2
回された
段 3
まん中のnums[mid] をnums[hi] とnums[mid] > nums[hi] なら、
段 4
前者なら lo = mid + 1、hi = mid にします。lo と hi が
解答
Python
Python
def rotated_min(nums):
lo, hi = 0, len(nums) - 1
while lo < hi:
mid = (lo + hi) // 2
if nums[mid] > nums[hi]:
lo = mid + 1
else:
hi = mid
return nums[lo]JavaScript
JavaScript
function rotatedMin(nums) {
let lo = 0;
let hi = nums.length - 1;
while (lo < hi) {
const mid =
Math.floor((lo + hi) / 2);
if (nums[mid] > nums[hi]) {
lo = mid + 1;
} else {
hi = mid;
}
}
return nums[lo];
}Go
Go
func rotatedMin(
nums []int,
) int {
lo, hi := 0, len(nums)-1
for lo < hi {
mid := (lo + hi) / 2
if nums[mid] > nums[hi] {
lo = mid + 1
} else {
hi = mid
}
}
return nums[lo]
}繰り返しのlo < hi です。lo <= hi にhi = mid が
計算量
- 時間は O(log n) です。
1 回比べる ごとに、 残りの 範囲が およそ 半分になります - 使う
記憶は O(1) です。 範囲の 両端と まん中の 番号だけを持ちます
よく ある間違い
- 左端と比べる。
nums[mid] > nums[lo]で右へ 進めると、 例 2 のような 回していない 並びで、 最小の 先頭を 飛ばして 右へ 行ってしまいます。 右端と 比べれば、 回していない 並びでも 1 つの 書き方で済みます hi = mid - 1にする。 まん中が右端以下の とき、 まん中が 答えの ことがあります。 例 1 で 範囲が 4 番の 1 と 5 番の 4 の 2 つに なった とき、 まん中の 1 を 外すと 答えを失います lo <= hiで回す。hi = midと組み合わせると、 範囲が 1 つに なった ところで 止まらなくなります - 切れ目を 1 つずつ探す。
前の 値より 小さい 所を 先頭から 探すと、 O(n) です
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「回された
並びは 小さい 順の 山が 2 つで、 答えは 後ろの 山の 先頭です。 まん中を 右端と 比べ、 まん中の 方が 大きければ 切れ目は 右なので 左端を まん中の 次へ、 そうでなければ まん中を 含めて 右端を 寄せます。 重なった 所が 答えで、 時間は O(log n)、 記憶は O(1) です。」
書き終えたら、
「例 1 では、
範囲 0 から 6 の まん中 3 番が 13、 右端が 6 で 13 の 方が 大きいので 4 から 6 にします。 まん中 5 番の 4 は 右端の 6 以下なので 4 から 5、 まん中 4 番の 1 は 4 以下なので 4 から 4 で 止まり、 答えは 1 です。」