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

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) となり、メモリ効率の良いインプレース処理が実現できます。

  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

  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 の場合、出