Pythonで連結リストを奇数番目・偶数番目のノードに並べ替える方法
問題の概要
片方向連結リスト(単方向リンクリスト)が与えられたとき、奇数番目のノードをすべて先頭に集め、その後に偶数番目のノードを続けるように並べ替えることを考えます。ここで重要なのは、「奇数・偶数」が指すのはノードが保持する値ではなく、リスト内でのノードの位置だという点です。さらに、余分なメモリを消費しないよう、インプレース(その場)で処理することが求められます。
たとえば、ノードが [1, 22, 13, 14, 25] の場合、結果は [1, 13, 25, 22, 14] となります。1番目・3番目・5番目のノード(1, 13, 25)が前半に、2番目・4番目のノード(22, 14)が後半に移動しているのがわかります。
解決のためのアプローチ
この問題は、2つのポインタを使うことで効率的に解決できます。1つ目のポインタ(head1)は奇数位置のノード列を、2つ目のポインタ(head2)は偶数位置のノード列をそれぞれ追跡します。各ノードの next ポインタを付け替えながらリストを進め、最後に奇数列の末尾へ偶数列の先頭をつなげれば完成です。
アルゴリズムの手順
- head が NULL、または head の次のノードが NULL の場合は、ノードが1つ以下であるため、そのまま head を返します。
- head1 := head、head2 := head.next、head2_beg := head.next として初期化します(head2_beg は偶数列の先頭を記憶しておくための変数です)。
- head2.next が NULL でなく、かつ head2.next.next も NULL でない間、次の処理を繰り返します。
- head1.next := head2.next(奇数列に次の奇数ノードを接続)
- head2.next := head2.next.next(偶数列に次の偶数ノードを接続)
- head1 := head1.next、head2 := head2.next として両ポインタを前進させます。
- ループ終了後、head2.next が NULL でない場合は、残りのノードを奇数列に接続します。
- head1.next := head2_beg として奇数列の末尾に偶数列の先頭をつなぎ、head2.next := NULL として偶数列の末尾を閉じます。
- head を返します。
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 oddEvenList(self, head):
if head == None or head.next ==None:
return head
head1=head
head2,head2_beg= head.next,head.next
while head2.next!= None and head2.next.next!= None:
head1.next = head2.next
head2.next = head2.next.next
head1 = head1.next
head2 = head2.next
if head2.next!=None:
head1.next = head2.next
head1 = head1.next
head1.next = head2_beg
head2.next = None
return head
ob1 = Solution()
head = make_list([1,22,13,14,25])
print_list(ob1.oddEvenList(head))
入力
[1,22,13,14,25]
出力
[1, 13, 25, 22, 14]
計算量について
このアルゴリズムはリスト全体を一度だけ走査するため、時間計算量は O(n) です。また、新しいリストや追加のデータ構造を作成せず、既存のノードのポインタを付け替えるだけなので、空間計算量は O(1) となり、メモリ効率の良いインプレース処理が実現できます。
-
Pythonでリスト内のK番目の偶数要素を検索する方法
リストの中から「K番目」の偶数要素を取り出したい場合、Pythonではリスト内包表記と%(剰余)演算子を組み合わせることで、非常にシンプルに実現できます。本記事では、具体的なサンプルコードとその動作解説を交えて紹介します。サンプルコード以下は、リストからK番目の偶数要素を取得する実装例です。my_list = [14, 63, 28, 32, 18, 99, 13, 61] print(The list is :) print(my_list) K = 3 print(The value of K is :) print(K) my_result = [element for eleme
-
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 の場合、出