Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonでリスト内のゼロを末尾へ移動する方法【インプレース処理・O(1)メモリ】

問題概要

数値のリスト nums が与えられたとき、リストをインプレース(元のリストを直接書き換える形)で更新し、すべてのゼロをリストの末尾へ移動することを考えます。その際、ゼロ以外の要素の相対的な順序は変更してはいけません。また、追加で使用できるメモリ領域は O(1) という制約があります。

たとえば、入力が [2,0,1,4,0,5,6,4,0,1,7] の場合、出力は [2, 1, 4, 5, 6, 4, 1, 7, 0, 0, 0] となります。

アルゴリズムの手順

この問題は、2つのポインタ(インデックス)を使うテクニックで効率的に解くことができます。手順は以下のとおりです。

  • L のサイズが 0 の場合は、空のリストを返します。
  • k := 0 と初期化します。k は「ゼロ以外の要素を書き込む位置」を表します。
  • i を 0 から L のサイズ - 1 まで順に処理します。
    • L[i] が 0 以外の場合、L[k] := L[i] として値を前方に詰め、k を 1 増やします。
  • 次に、j を k から L のサイズ - 1 まで順に処理します。
    • L[j] := 0 として、残りの部分をゼロで埋めます。
  • 最後に L を返します。

この方法では、リスト全体を2回走査するだけで済み、余分なリストを作成しないため、追加メモリは O(1) で抑えられます。

実装例

以下のコードで具体的な実装を確認できます。

class Solution:
    def solve(self, L):
        if len(L) == 0:
            return []
        k = 0
        for i in range(len(L)):
            if L[i] != 0:
                L[k] = L[i]
                k += 1
        for j in range(k, len(L)):
            L[j] = 0
        return L

ob = Solution()
L = [2, 0, 1, 4, 0, 5, 6, 4, 0, 1, 7]
print(ob.solve(L))

入力

[2,0,1,4,0,5,6,4,0,1,7]

出力

[2, 1, 4, 5, 6, 4, 1, 7, 0, 0, 0]

計算量

  • 時間計算量:O(n) — リストを2回走査するだけです。
  • 空間計算量:O(1) — 追加のデータ構造を使用しません。

補足:別のアプローチとの比較

Python では list.remove(0)list.append(0) を組み合わせる方法も考えられますが、remove() は要素を先頭から探すため O(n) の操作となり、ゼロが多いリストでは非効率です。本記事で紹介した2ポインタ方式は、どのような入力に対しても安定して O(n) で動作するため、実務やコーディング面接でも推奨される手法です。

  1. Pythonでタプルのリストをリストのリストに変換する方法

    Pythonでは、要素がタプルになっているリストを扱うことがあります。その後のデータ処理において、タプルのままでは扱いにくいケースも多く、リスト形式に変換してから処理を行いたい場面が出てきます。この記事では、タプルのリストをリストのリスト(ネストされたリスト)に変換する代表的な2つの方法を、具体的なコード例とともに解説します。方法1:リスト内包表記を使う最もシンプルで直感的なのが、リスト内包表記を使う方法です。forループで各要素(タプル)を1つずつ取り出し、list()関数を適用することで、新しいリストを作成していきます。コード例listA = [(Mon, 3), (Wed, 4), (F

  2. Pythonで配列内のゼロを右端に移動するアルゴリズム

    数値を格納する配列を考えてみましょう。この配列には、ゼロ以外の値とゼロの値が混在しています。ここでの課題は、他の数値の相対的な順序を変えずに、すべてのゼロを配列の右端(末尾)へ移動させることです。 例えば、配列が [0, 1, 5, 0, 3, 8, 0, 0, 9] の場合、処理後の最終的な配列は [1, 5, 3, 8, 9, 0, 0, 0, 0] となります。 解決手順 この問題は、次の手順で解くことができます。 挿入位置を記録するためのインデックス index を 0 で初期化します。 i = 0 から配列 A の長さまで繰り返します。 A[i] != 0 の場合: A[in