Pythonで連結リストを反転する方法|再帰を使った実装をわかりやすく解説
連結リスト(リンクリスト)が与えられたとき、それを逆順に並べ替えることを考えます。たとえば、リストが 1 → 3 → 5 → 7 の場合、反転後の新しいリストは 7 → 5 → 3 → 1 となります。
解き方のアプローチ
この問題は、再帰を使った手順「solve(head, back)」を定義することで解決できます。具体的な流れは以下のとおりです。
- リストの反転を再帰的に行う手順 solve(head, back) を定義する
- head が存在しない場合は、head をそのまま返す
- temp := head.next として、次のノードを一時的に保存する
- head.next := back として、ポインタの向きを前のノードへ逆向きにする
- back = head として、現在のノードを「前のノード」として記録する
- temp が空の場合は、head を返して処理を終了する
- head = temp として、次のノードへ進む
- solve(head, back) を再帰的に呼び出す
実装例
以下の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(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
return self.solve(head, None)
def solve(self, head, back):
if not head:
return head
temp = head.next
head.next = back
back = head
if not temp:
return head
head = temp
return self.solve(head, back)
list1 = make_list([1, 3, 5, 7])
ob1 = Solution()
list2 = ob1.reverseList(list1)
print_list(list2)
入力
list1 = [1,3,5,7]
出力
[7, 5, 3, 1]
処理のポイント
このアルゴリズムでは、各ノードの next ポインタを前のノードに向けることで、リスト全体の向きを反転させています。back 変数が「これまで処理済みの部分リストの先頭」を保持し、再帰呼び出しがリストの末尾に到達した時点で、最後のノードが新しい先頭となり、完全に反転されたリストが完成します。
-
Pythonで連結リストのサイクル(循環)を検出する方法
連結リストのサイクル検出とは連結リスト(Linked List)の中にサイクル(循環)が存在するかどうかを判定する問題を考えてみましょう。この問題では、サイクルの有無を表現するために整数値のポインタ pos を使用します。pos は、リストの末尾ノードが接続されている位置を示します。つまり、pos = -1 の場合はサイクルが存在しないことを意味します。例えば、連結リストが [5, 3, 2, 0, -4, 7] で pos = 1 の場合、末尾ノード(7)が2番目のノード(3)に接続されているため、サイクルが存在することになります。解法のアプローチ:ハッシュセットを使う最もシンプルな方法は、
-
Pythonで連結リストのノードを削除する方法
連結リスト(リンクリスト)にいくつかの要素が格納されているとします。ここでの課題は、指定されたノードをリストから削除する関数を作成することです。例えば、リストが 1 → 3 → 5 → 7 → 9 の場合、値 3 を削除すると、結果は 1 → 5 → 7 → 9 になります。削除の基本的な考え方削除したいノードを指すポインタ「node」が与えられている場合、以下の2つの操作を実行することでノードを削除できます。node.val = node.next.val — 次のノードの値を現在のノードにコピーするnode.next = node.next.next — 現在のノードの参照先を、次の次のノ