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

Pythonで連結リスト(リンクリスト)から重複する要素を削除するプログラム

数値を格納した連結リスト(リンクリスト)が与えられたとき、複数回出現する要素を削除し、それぞれの値を1つだけ残すことを考えます。その際、元の連結リストにおける出現順序は維持しなければなりません。

例えば、入力が [2 -> 4 -> 6 -> 1 -> 4 -> 6 -> 9] の場合、重複が取り除かれた結果は [2 -> 4 -> 6 -> 1 -> 9] となります。最初に出現した「4」と「6」は保持され、2回目以降の出現だけが削除されている点に注目してください。

アルゴリズムの考え方

この問題は、セット(set)を使って既に見た値を記録することで効率的に解けます。具体的な手順は以下の通りです。

  • ノードが null でない場合:
    • 空のセット l を作成する
    • 一時ポインタ temp を先頭ノードに設定する
    • temp の値をセット l に追加する
    • temp の次のノードが存在する間、以下を繰り返す
      • 次のノードの値がセット l に含まれていない場合:その値を l に追加し、temp を次のノードへ進める
    • すでに含まれている場合:次のノードをスキップして削除する(temp.next を temp.next.next に付け替える)
  • 最後に先頭ノード node を返す

セットへの追加・検索は平均 O(1) で行えるため、全体の計算量は O(n)、必要な追加メモリも O(n) となります。

実装例

それでは、実際のPythonコードを見てみましょう。

class ListNode:
   def __init__(self, data, next = None):
      self.val = data
      self.next = next

def make_list(elements):
   head = ListNode(elements[0])
   for element in elements[1:]:
      ptr = head
      while ptr.next:
         ptr = ptr.next
      ptr.next = ListNode(element)
   return head

def print_list(head):
   ptr = head
   print('[', end = "")
   while ptr:
      print(ptr.val, end = ", ")
      ptr = ptr.next
   print(']')

class Solution:
   def solve(self, node):
      if node:
         l = set()
         temp = node
         l.add(temp.val)
         while temp.next:
            if temp.next.val not in l:
               l.add(temp.next.val)
               temp = temp.next
            else:
               temp.next = temp.next.next
         return node

ob = Solution()
head = make_list([2, 4, 6, 1, 4, 6, 9])
print_list(ob.solve(head))

入力

[2, 4, 6, 1, 4, 6, 9]

出力

[2, 4, 6, 1, 9]

コードのポイント

  • ListNodeクラス:連結リストの各ノードを表します。値 val と次ノードへの参照 next を持ちます。
  • make_list関数:Pythonのリストから連結リストを構築するヘルパー関数です。
  • solveメソッド:セット l で出現済みの値を管理しながらリストを走査し、重複ノードをその場で切り離します。新しいリストを作るのではなく、既存のリストのポインタを書き換えているため、余分なノード生成が不要です。

このように、セットによる「見たことのある値」の管理と、ポインタの付け替えを組み合わせることで、順序を保ったまま重複要素だけを効率よく削除できます。

  1. Pythonで行列内の重複要素を含む行を削除する方法

    行列(リストのリスト)の中から、重複した要素を含む行を削除したい場合、リスト内包表記とset()関数を組み合わせることで、簡潔に実装できます。 考え方 set()は重複しない要素のみを保持するため、ある行をsetに変換したときの長さが元の行の長さと一致すれば、その行には重複が存在しないことになります。この性質を利用して、重複を含まない行だけを抽出します。 サンプルコード 以下に具体的な実装例を示します。 my_list = [[34, 23, 34], [17, 46, 47], [22, 14, 22], [28, 91, 19]] print(元のリスト:) print(my_list)

  2. Pythonで連結リストのm個のノードを保持した後にn個のノードを削除するプログラム

    始点ノードが「head」である連結リストと、2つの整数 m と n が与えられたとします。リストを走査しながら、先頭から数えて m 個のノードを残した直後の n 個のノードを削除する処理を、連結リストの末尾に到達するまで繰り返します。処理は head ノードから開始し、最後に変更後の連結リストを返します。今回扱う連結リストの構造は次のように定義されています。Node value : <整数値> next : <次のノードへのポインタ>例えば、入力が elements = [1, 2, 3, 4, 5, 6, 7, 8]、m = 3、n = 1 の場合、出