Pythonで連結リストを先頭と末尾から交互に並べ替える方法
片方向連結リスト(単方向リンクリスト)が与えられたとき、ノードを「末尾のノード → 先頭のノード → 末尾から2番目のノード → 先頭から2番目のノード…」という順序で並べ替えることを考えます。
例えば、入力が [1,2,3,4,5,6,7,8,9] の場合、出力は [9, 1, 8, 2, 7, 3, 6, 4, 5] となります。
解決のための手順
この問題は、以下の手順で解くことができます。
- 現在のノード
cを先頭ノードに設定し、値を一時保存するための空のリストlを用意します。 cが null でない間、cの値をリストlの末尾に追加し、cを次のノードへ進めます。これですべてのノードの値がリストにコピーされます。cを再び先頭ノードに戻します。cが null でなく、かつリストlが空でない間、以下を繰り返します。- リスト
lの末尾の要素を取り出してcの値に代入し、cを次のノードへ進めます。 cが null になった場合は、そこでループを抜けます。- そうでなければ、リスト
lの先頭の要素を取り出してcの値に代入し、cを次のノードへ進めます。
- リスト
- 最後にノードを返します。
実装例
それでは、以下の実装を見て理解を深めましょう。
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):
c = node
l = []
while c:
l.append(c.val)
c = c.next
c = node
while c and l:
c.val = l.pop()
c = c.next
if c == None:
break
c.val = l.pop(0)
c = c.next
return node
ob = Solution()
head = make_list([1,2,3,4,5,6,7,8,9])
print_list(ob.solve(head))
入力
[1,2,3,4,5,6,7,8,9]
出力
[9, 1, 8, 2, 7, 3, 6, 4, 5]
アルゴリズムのポイント
この手法では、まず連結リストのすべての値をPythonのリストにコピーします。その後、pop() でリストの末尾から、pop(0) でリストの先頭から交互に値を取り出しながら、元の連結リストの各ノードに書き戻していきます。
この方法の利点は、複雑なポインタ操作を行うことなく、ノードの値の書き換えだけで目的の順序を実現できる点です。計算量はノード数を n とすると O(n)、必要な追加メモリも O(n) となります。
-
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 の場合、出
-
【Python】連結リストをジグザグ二分木に変換するプログラムの書き方
問題の概要単方向連結リスト(片方向リンクリスト)が与えられたとき、次のルールに従って二分木へ変換することを考えます。連結リストの先頭ノード(head)が、二分木のルートになります。それ以降の各ノードは、その値が親ノードより小さい場合は左の子に、そうでない場合は右の子になります。たとえば、入力が [2,1,3,4,0,5] の場合、変換後の二分木は次のような「ジグザグ」形状になります。解き方の手順この問題は、再帰的に呼び出す関数 solve() を定義すると、シンプルに解くことができます。具体的な手順は以下の通りです。ノードを引数として受け取る関数 solve() を定義します。ノードが nul