二分探索で 行ごとに 並んだ 表から値を探す
各行が
海外で定番の問題リスト 4 本には入っていません
問題
整数のmatrix とtarget をtarget がtrue、false を
- 表は m 行 n 列で、
どの 行も 左から 小さい 順に 並んでいます - どの
行も、 頭の 値が 1 つ前の 行の 最後の 値より 大きくなっています。 つまり、 上の 行から 左から 右へ 読むと、 全体が 小さい 順の 1 本の 並びになります - 同じ値は 2 回出てきません
- m と n は
どちらも 1 以上 100 以下、 値と targetはどれも -10000 以上 10000 以下です - 時間は O(log(m × n)) で
解いてください
入力と出力の例
例 1
社員番号の
例 2
15 は 1 行目の
例 3
1 列だけの
面接での聞かれ方
二分探索の
- 「行ごとに
並んだ 表から 値を 探してください。 全部を 見るより 速く できますか?」 - 書き終えた
あとに 「行の 頭が 前の 行の 最後より 大きい、という 決まりが 無かったら どうしますか?」と 続きを 聞かれる ことがあります。 その ときは 右上の 角から 始め、 大きければ 左へ、 小さければ 下へ 進む O(m + n) の 書き方になります - 「行で 1 回、
列で 1 回の 2 段の 二分探索でも 書けますか?」と 聞かれる こともあります
ミドルの
ヒント
まだ開いていません
付箋は 4 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3
ヒント 4答えに近い
アルゴリズムのチートシートの「ソートと二分探索」に、
関わる学び
二分探索は、
まず 考える手順
段 1
まずは
段 2
上のk // n 行目、k % n 列目に
段 3
番号 0 から m × n − 1 のmid をtarget と
段 4
範囲がtarget は
解答
Python
Python
def sorted_matrix_search(
matrix, target
):
m = len(matrix)
n = len(matrix[0])
lo, hi = 0, m * n - 1
while lo <= hi:
mid = (lo + hi) // 2
row = matrix[mid // n]
v = row[mid % n]
if v == target:
return True
if v < target:
lo = mid + 1
else:
hi = mid - 1
return FalseJavaScript
JavaScript
function sortedMatrixSearch(
matrix, target
) {
const m = matrix.length;
const n = matrix[0].length;
let lo = 0;
let hi = m * n - 1;
while (lo <= hi) {
const mid =
Math.floor((lo + hi) / 2);
const v = matrix[
Math.floor(mid / n)
][mid % n];
if (v === target) {
return true;
}
if (v < target) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
return false;
}Go
Go
func sortedMatrixSearch(
matrix [][]int, target int,
) bool {
m := len(matrix)
n := len(matrix[0])
lo, hi := 0, m*n-1
for lo <= hi {
mid := (lo + hi) / 2
v := matrix[mid/n][mid%n]
if v == target {
return true
}
if v < target {
lo = mid + 1
} else {
hi = mid - 1
}
}
return false
}mid // n がmid % n が
計算量
- 時間は O(log(m × n)) です。
1 回比べる ごとに、 残りの 範囲が 半分になります - 使う
記憶は O(1) です。 範囲の 両端と まん中の 番号だけを持ちます
よく ある間違い
- 行の
数 m で割る。 番号から 位置に 直すときは、 1 行の 長さ n で 割ります。 m で 割ると、 行と 列の 数が 違う 表で 別の マスを読みます - 範囲の
右端を m × n にする。 lo <= hiで回す 書き方なら、 右端は 最後の 番号の m × n − 1 です。 m × n に すると 表の 外を読みます - 行を
探す段で、 行の 頭だけを 見て終える。 2 段の 二分探索で 書く とき、 targetは「頭が target以下の最後の 行」に あります。 頭が ちょうど 同じ 行だけを 探すと、 例 1 の 21 を 見落とします - 全部を 1 本の
並びに 作り直す。 並びを 作るだけで O(m × n) の 時間と 記憶を 使い、 二分探索に した 意味が なくなります
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「上の
行から 読むと 全体が 小さい 順の 1 本の 並びに なるので、 番号 0 から m × n − 1 で 二分 探索します。 番号 k は k を 列の 数で 割った 商が 行、 余りが 列です。 時間は O(log(m × n))、 記憶は O(1) です。」
書き終えたら、
「例 1 では 12 個なので
範囲は 0 から 11 です。 まん中の 5 番は、 4 で 割った 商 1 と 余り 1 から 上から 2 行目の 左から 2 番目で 21、 目標と 同じなので true です。 15 なら、 5 番の 21 より 小さいので 0 から 4、 まん中の 2 番は 9 で 小さいので 3 から 4、 3 番は 14、 4 番は 17 で、 範囲が 空に なって false です。」