ゆめさくエンジニア研究所

足して​目標に​なる​ 2 つの位置

整数の​並びから、​足すと​目標の​数に​なる​ 2 つを​探し、​その​位置を​返す。​見た​数を​辞書に​覚えておくと、​並びを​ 1 回なめるだけで​見つかります。

問題

整数の並び nums と、整数 target を受け取ります。nums の中から、足すと target になる 2 つの数を選び、その位置 (0 から数えた番号) を小さい順に並べて返す関数を書いてください。

  • 答えになる組は、ちょうど 1 組だけあるものとします
  • 同じ位置の数を 2 回使うことはできません。同じ値が別の位置に 2 つあれば、その 2 つは使えます
  • nums の長さは 2 以上 10000 以下、値はどれも絶対値が 10 億以下です

入力と出力の例

例 1

入力

nums = [3, 8, 12, 5]
target = 17

出力

[2, 3]

例 2

同じ値でも、位置が違えば別の数として使えます。

入力

nums = [6, 1, 6]
target = 12

出力

[0, 2]

例 3

負の数も入ります。

入力

nums = [-4, 10, 7, 2]
target = 3

出力

[0, 2]

面接での聞かれ方

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

  • 「整数の配列と目標の数があります。足して目標になる 2 つの位置を返してください」
  • 書き終えたあとに「いまの書き方の計算量は?」「もっと速くできますか?」と続けて聞かれます
  • 「答えが無いときはどうしますか?」と、問題文に無い場合を聞かれることもあります

最初の一文だけで書き始めず、答えがいつも 1 組あるのか、同じ位置を 2 回使ってよいのかを、先に確かめてから書くと落ち着いて進められます。

まず考える手順

段 1

まずは素直に、2 つの組を全部試す書き方を考えます。1 つ目の位置 i と、それより後ろの位置 j を 2 重の繰り返しで回し、足して target になれば返します。これでも正しく動きます。

段 2

全部の組を試すと、長さが 10000 のとき、足し算は 5000 万回ほどになります。そこで、1 つ目の数を決めたら、相手は target から引いた数に決まることに目を向けます。「相手の数がもう出てきたか」をすぐに調べられれば、繰り返しは 1 重で済みます。

段 3

すぐに調べるには、辞書 (Python の dict、JavaScript の Map) を使います。数を 1 つ見るたびに、まず相手が辞書にあるかを調べ、無ければ「この値はこの位置にあった」と辞書に書き足します。調べてから書き足す順にすると、同じ位置を 2 回使うことが起きません。

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

解答

Python

Python

def pair_with_target(
    nums, target
):
    seen = {}
    for i, x in enumerate(nums):
        need = target - x
        if need in seen:
            j = seen[need]
            return [j, i]
        seen[x] = i
    return []

JavaScript

JavaScript

function pairWithTarget(
  nums, target
) {
  const seen = new Map();
  const n = nums.length;
  for (let i = 0; i < n; i++) {
    const x = nums[i];
    const need = target - x;
    if (seen.has(need)) {
      const j = seen.get(need);
      return [j, i];
    }
    seen.set(x, i);
  }
  return [];
}

答えは必ず 1 組あるので、最後の return [] に来ることはありません。面接で「無いときは?」と聞かれたら、空の並びを返すと決めてある、と答えられるように置いてあります。

計算量

  • 時間は O(n) です。並びを前から 1 回なめ、辞書を調べるのも書き足すのも、平均して一定の手間で済みます
  • 使う記憶は O(n) です。最悪の場合、ほぼ全部の数を辞書に覚えます
  • 段 1 の 2 重の繰り返しは、時間が O(n²)、記憶は O(1) です。記憶を使う代わりに時間を縮めた、という取り引きになっています

よくある間違い

  • 先に書き足してから調べる。 seen[x] = i を先に置くと、target がちょうど x の 2 倍のとき、自分自身を相手として見つけてしまいます。例 2 の [6, 1, 6] で 6 を 1 つしか使わずに答えたことになります
  • 値で並べ替えてから探す。並べ替えると元の位置が分からなくなります。並べ替えるなら、位置を組にして持ち歩く必要があります
  • 返す順を気にしない。辞書から取り出した位置は、いま見ている位置より必ず前なので、[seen[need], i] の順に返せば小さい順になります

面接での話し方の例

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

「まず、全部の組を試す書き方なら O(n²) で解けます。ただ、1 つ目の数が決まると相手の数も決まるので、見た数を辞書に覚えておけば、並びを 1 回なめるだけで探せます。時間は O(n) で、その代わりに記憶を O(n) 使います。」

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

「例 2 の [6, 1, 6] でたどります。最初の 6 では相手の 6 がまだ辞書に無いので、6 は 0 番と書き足します。1 も同じく書き足します。最後の 6 で相手の 6 が辞書にあり、0 番なので [0, 2] を返します。調べてから書き足しているので、同じ 6 を 2 回使うことはありません。」

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

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