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

Pythonで2つのソート済みリストをマージして1つのソート済みリストを作成する方法

2つのソート済みリスト A と B が与えられたとき、それらをマージして、1つのソート済みリスト C を作成することを考えます。なお、2つのリストのサイズは異なっていても構いません。

例えば、A = [1, 2, 4, 7]、B = [1, 3, 4, 5, 6, 8] の場合、マージ後のリスト C は [1, 1, 2, 3, 4, 4, 5, 6, 7, 8] となります。

アルゴリズムの考え方

この問題は、2つのリストを先頭から順に比較しながら要素を取り出していく「マージ処理」で解くことができます。各リストに対してポインタ(インデックス)を1つずつ用意し、小さい方の要素を結果のリストに追加していきます。手順は以下の通りです。

  • 結果を格納するための新しいリスト x を用意する
  • インデックス i = 0、j = 0 と初期化する
  • i が lst0 のサイズ未満 かつ j が lst1 のサイズ未満である間、以下を繰り返す
    • lst0[i] > lst1[j] の場合:x の末尾に lst1[j] を追加し、j を +1 する
    • lst0[i] < lst1[j] の場合:x の末尾に lst0[i] を追加し、i を +1 する
    • それ以外(等しい場合):x の末尾に lst0[i] と lst1[j] の両方を追加し、i と j をそれぞれ +1 する
  • ループ終了後、lst0 に残った要素があればすべて x に追加する
  • 同様に、lst1 に残った要素があればすべて x に追加する
  • x を返す

どちらか一方のリストの要素を使い切った後は、もう片方のリストに残っている要素はすでにソートされているため、そのまま順番に追加するだけで正しい結果が得られます。

実装例

それでは、実際のコードを見て理解を深めましょう。

class Solution:
    def solve(self, lst0, lst1):
        x = []
        i = 0
        j = 0
        while(i < len(lst0) and j < len(lst1)):
            if(lst0[i] > lst1[j]):
                x.append(lst1[j])
                j = j + 1
            elif(lst0[i] < lst1[j]):
                x.append(lst0[i])
                i = i + 1
            else:
                x.append(lst0[i])
                x.append(lst1[j])
                i = i + 1
                j = j + 1
        while(i < len(lst0)):
            x.append(lst0[i])
            i = i + 1
        while(j < len(lst1)):
            x.append(lst1[j])
            j = j + 1
        return x

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

入力

[1, 2, 4, 7], [1, 3, 4, 5, 6, 8]

出力

[1, 1, 2, 3, 4, 4, 5, 6, 7, 8]

計算量について

このアルゴリズムの時間計算量は O(m + n) です。ここで m と n はそれぞれ lst0 と lst1 の要素数です。各要素は必ず一度だけ比較・追加されるため、非常に効率的です。また、空間計算量も結果リストの分だけの O(m + n) となります。

なお、Pythonでは標準ライブラリの heapq.merge() を使うことでも、ソート済みイテラブルを効率的にマージできます。ただし、マージソートの仕組みを理解する上で、今回のような手動での実装は非常に良い学習材料になります。

  1. Pythonでソート済みリストの順序を保ったまま要素を挿入する2つの方法

    本記事では、ソート済みのリストに対して、その並び順を崩すことなく新しい要素を挿入する方法について解説します。 問題文 リストが与えられたとき、既存のソート順を維持したまま、指定した要素を適切な位置に挿入する必要があります。 この問題を解くには、主に以下の2つのアプローチがあります。 アプローチ1:線形探索による力まかせ法(ブルートフォース) まず、挿入すべき位置をリストの先頭から順に走査して見つけ出し、そこへ要素を挿入するというシンプルな方法です。挿入する要素より大きい値が最初に現れた位置に、新しい要素を差し込みます。 コード例 n: index = i

  2. Pythonで2つの辞書をマージするプログラムの書き方

    この記事では、Pythonを使って2つの辞書(ディクショナリ)を1つに結合(マージ)するプログラムを紹介します。辞書の結合には、組み込みメソッドである update() を使用します。update() メソッドは、引数に渡した辞書の要素を呼び出し元の辞書へ追加することで、2つの辞書を統合できます。 なお、update() の戻り値は None です。つまり新しい辞書が生成されるわけではなく、既存の辞書そのものが直接更新されるという点に注意してください。 実行例 入力:: A = {AAA: 10} B = {BBB: 20} 出力:: C = {BBB: 20, AAA: 10} アルゴリ