ゆめさくエンジニア研究所
二分探索問題 14

入れる​位置を探す

小さい​順の​並びで、​目当ての数が​あれば​その​位置を、​無ければ​順を​崩さずに​入れる​位置を​返す。​二分探索が​止まった​ときの​左の​端が​何を​指すかを​考える​練習です。

問題

小さい順に並んだ整数の並び nums と、整数 target を受け取ります。nums の中に target があれば、その位置 (0 から数えた番号) を返してください。無ければ、小さい順を崩さずに target を入れられる位置を返してください。

  • nums の値は小さい順に並び、同じ値は 2 回出てきません
  • nums の長さは 0 以上 10000 以下、値はどれも -10000 以上 10000 以下です。空のときの答えは 0 です
  • 時間は O(log n) で解いてください

入力と出力の例

例 1

target が並びにあれば、その位置を返します。

入力

nums = [-3, 2, 7, 11]
target = 7

出力

2

例 2

8 は 7 と 11 の間に入るので、11 がいる位置が答えです。

入力

nums = [-3, 2, 7, 11]
target = 8

出力

3

例 3

どの数より大きければ、最後の後ろに入ります。

入力

nums = [1, 6]
target = 20

出力

2

面接での聞かれ方

面接では、問題文がもっと短く渡されることが多いです。

  • 「ソート済みの配列と目標の数があります。あればその位置、無ければ入れる位置を返してください」
  • 二分探索の問題のすぐあとに、続きとして出されることがよくあります
  • 書き終えたあとに「なぜ最後の left が答えになるのですか?」と聞かれます

前の問題との違いは、見つからなかったときに何を返すかだけです。入れる位置とは「target 以上の数が最初に出てくる位置」だ、と言い換えてから書くと、考えが整います。

まず考える手順

段 1

まずは素直に、前から 1 つずつ見ていく書き方を考えます。target 以上の数に初めて出会った位置を返し、最後まで出会わなければ並びの長さを返します。正しく動きますが、時間は O(n) です。

段 2

問題 13 の二分探索をそのまま使い、見つからなかったときに -1 の代わりに何を返すかを考えます。範囲は両端を含む left と right で持ち、left <= right の間だけ繰り返す形は同じです。

段 3

繰り返しの間、left より左の数はどれも target より小さく、right より右の数はどれも target より大きい、という決まりが保たれます。繰り返しが終わると left は right の 1 つ右に来るので、left は「target より大きい数の最初の位置」を指します。そこが入れる位置なので、-1 の代わりに left を返せば答えになります。

ここから​解答です。​先に​自分で​書いてから​読むと、​考え方が​残ります。

解答

Python

Python

def insert_position(
    nums, target
):
    left = 0
    right = len(nums) - 1
    while left <= right:
        both = left + right
        mid = both // 2
        if nums[mid] == target:
            return mid
        if nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    return left

JavaScript

JavaScript

function insertPosition(
  nums, target
) {
  let left = 0;
  let right = nums.length - 1;
  while (left <= right) {
    const mid = Math.floor(
      (left + right) / 2
    );
    if (nums[mid] === target) {
      return mid;
    }
    if (nums[mid] < target) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }
  return left;
}

問題 13 の解答と違うのは、最後の 1 行だけです。nums が空のときは繰り返しに入らず、left の 0 をそのまま返します。

計算量

  • 時間は O(log n) です。1 回見るたびに範囲がおよそ半分になります
  • 使う記憶は O(1) です。持つのは left、right、mid の 3 つの数だけです
  • 段 1 の前から見る書き方は O(n) です。答えが「入れる位置」に変わっても、二分探索の速さはそのまま使えます

よくある間違い

  • 最後に right を返す。 繰り返しが終わったとき、right は「target より小さい数の最後の位置」を指しています。入れる位置はその 1 つ右なので、left を返します
  • 最後の後ろを忘れる。例 3 のように、答えが並びの長さと同じ値になることがあります。位置は 0 から長さまでの範囲で返ると考えておきます
  • 空の並びで落ちる。先に nums[0] を見るような書き方をすると、空のときに範囲の外を読みます。解答の形なら、空でもそのまま 0 が返ります

面接での話し方の例

書き始める前に、方針を短く口に出します。

「入れる位置は、目標以上の数が最初に出てくる位置と言い換えられます。普通の二分探索で探し、見つからなかったときは最後の左の端を返します。時間は O(log n) です。」

書き終えたら、例を 1 つ手でたどって見せます。

「例 2 の [-3, 2, 7, 11] に 8 を入れます。真ん中の 2 は小さいので左の端を 7 の位置へ、次の真ん中の 7 も小さいので左の端を 11 の位置へ動かします。真ん中の 11 は大きいので右の端を 7 の位置へ戻し、ここで範囲が空になります。左の端は 3 で、11 の手前に入れる位置です。」

解答を動かした版 Python 3.12.14Node.js 22.23.4確認日 2026年10月24日

コーディング面接問題の一覧へ戻る