ゆめさくエンジニア研究所
2 つの指問題 07

0 を​後ろへ寄せる

整数の​並びの​ 0 を​全部後ろへ​寄せ、​0 でない​数の​順は​保ちます。​書き込む位置の​指と​読む指の​ 2 つを​使い、​新しい​並びを​作らずに​入れ替える​練習です。

問題

整数の並び nums を受け取ります。nums の中の 0 を全部後ろへ寄せ、0 でない数は元の順のまま前に並べる関数を書いてください。

  • 新しい並びを作らず、受け取った nums の中で入れ替えます
  • 入れ替え終わったら、最後にその nums を返します。確かめは戻り値で見ます
  • nums の長さは 0 以上 10000 以下、値はどれも絶対値が 10 億以下です

入力と出力の例

例 1

入力

nums = [0, 4, 0, 7, 2]

出力

[4, 7, 2, 0, 0]

例 2

0 でない数の順は変えません。負の数も 0 でない数です。

入力

nums = [5, 0, -3, 0, 0, 1]

出力

[5, -3, 1, 0, 0, 0]

例 3

0 が 1 つも無ければ、そのまま返します。

入力

nums = [9, 8, 6]

出力

[9, 8, 6]

面接での聞かれ方

面接では、短い一文で渡されることが多いです。

  • 「配列の 0 を末尾に移してください。ほかの数の順は保ってください」
  • 「追加の配列を使わずにできますか?」と、記憶の使い方を条件に足されることがあります
  • 書き終えたあとに「書き込みの回数を減らせますか?」と聞かれることもあります

新しい並びを作ってよいのか、0 でない数の順を保つ必要があるのかを、書く前に確かめておくと迷いません。

まず考える手順

段 1

まずは素直に、新しい並びを 2 つ作る書き方を考えます。0 でない数を前から集めた並びと、0 を集めた並びを作り、つなげれば答えです。正しく動きますが、問題の決まりにある「新しい並びを作らない」を守れていません。

段 2

新しい並びを作らないなら、0 を見つけるたびに後ろの数を 1 つずつ前へずらす書き方もできます。ただ、0 が多いと、ずらす手間が何度も重なります。長さが 10000 で半分が 0 なら、千万回を超える移動になります。

段 3

そこで指を 2 つ使います。読む指は前から順に全部を見て、書き込む指は「次に 0 でない数を置く位置」を指します。読む指が 0 でない数に出会ったら、書き込む指の位置と入れ替え、書き込む指を 1 つ進めます。入れ替えにすると、0 は自然と後ろへ押し出されます。

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

解答

Python

Python

def move_zeros(nums):
    n = len(nums)
    write = 0
    for read in range(n):
        if nums[read] == 0:
            continue
        tmp = nums[write]
        nums[write] = nums[read]
        nums[read] = tmp
        write += 1
    return nums

JavaScript

JavaScript

function moveZeros(nums) {
  const n = nums.length;
  let write = 0;
  let read = 0;
  while (read < n) {
    if (nums[read] !== 0) {
      const tmp = nums[write];
      nums[write] = nums[read];
      nums[read] = tmp;
      write++;
    }
    read++;
  }
  return nums;
}

書き込む指 write より前には、いつも 0 でない数だけが元の順で並んでいます。読む指が最後まで進めば、write から後ろは全部 0 になっています。

計算量

  • 時間は O(n) です。読む指が並びを前から 1 回なめるだけで済みます
  • 使う記憶は O(1) です。指 2 つと、入れ替えに使う 1 つの置き場だけです
  • 段 1 の書き方は、時間は O(n) ですが、記憶が O(n) 要ります。段 2 の書き方は、記憶は O(1) でも時間が最悪 O(n²) になります

よくある間違い

  • 0 を見つけたら消して末尾に足す。繰り返しの途中で並びの長さや位置が動き、数を読み飛ばします。Python の remove や JavaScript の splice は、それ自体も中で数をずらすので遅くなります
  • 入れ替えずに上書きだけして、0 を埋め忘れる。 0 でない数を前へ写すだけの書き方なら、最後に write から後ろを 0 で埋める手順が要ります
  • 並べ替えで済ませる。「0 かどうか」で並べ替えると、0 でない数の順が保たれない書き方になりやすく、時間も O(n log n) かかります

面接での話し方の例

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

「0 でない数と 0 を別の並びに集めれば簡単ですが、追加の記憶を使わない条件なので、指を 2 つ使います。読む指で前から見て、0 でない数を書き込む指の位置と入れ替えます。時間は O(n)、記憶は O(1) です。」

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

「例 1 の [0, 4, 0, 7, 2] でたどります。最初の 0 は飛ばします。4 で書き込む位置の 0 番と入れ替えて [4, 0, 0, 7, 2] です。次の 0 も飛ばし、7 を 1 番と入れ替え、2 を 2 番と入れ替えると [4, 7, 2, 0, 0] になります。」

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

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