[Jianzhi Offer] 52. 2 つのリンクされたリストの最初の共通ノード。難易度: 短答 -- 中程度。ダブルポインタ方式が美しすぎる

1. トピック

トピックリンク: Jianzhi Offer 52. 2 つのリンクされたリストの最初の共通ノード

2 つのリンクされたリストを入力し、最初の共通ノードを見つけます。

ここに画像の説明を挿入
ここに画像の説明を挿入
知らせ:

如果两个链表没有交点,返回 null.
在返回结果后,两个链表仍须保持原有的结构。
可假定整个链表结构中没有循环。
程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

ここで、時間計算量と空間計算量の要件に注意を払う必要があります。

2. 私の解決策: ハッシュ テーブル、空間複雑度 0(n) は要件を満たしていません

2.1 アルゴリズムのアイデア

2 つのリンク リストが交差するかどうかを判断するには、ハッシュ セットを使用してリンク リスト ノードを保存します。

まず、リンク リスト headA を走査し、リンク リスト headA 内の各ノードをハッシュ セットに追加します。次に、リンク リスト headB を走査し、走査したノードごとに、そのノードがハッシュ セット内にあるかどうかを判断します。

  • 現在のノードがハッシュ セットに含まれていない場合は、次のノードのトラバースを続けます。
  • 現在のノードがハッシュ セット内にある場合、後続のすべてのノードはハッシュ セット内にあります。つまり、現在のノードから始まるすべてのノードは 2 つのリンク リストの共通ノードであるため、リンク リストの headB で最初に探索されるノードは次のようになります。ハッシュ セットのギリシャ語セットのノードは、2 つのリンクされたリストの最初の共通ノードであり、このノードを返します。

リンク リスト headB 内のすべてのノードがハッシュ セットにない場合、2 つのリンク リストは互いに素であり、null が返されます。

2.2 コード

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        hashmap={
    
    }
        while headA:
            hashmap[headA]=headA
            headA=headA.next
        while headB:
            if headB in hashmap:
                return headB
            headB=headB.next
        return None      

リンクされたリスト headA と headB の長さがそれぞれ m と n であると仮定すると、リンクされたリストにすべてのノードを格納するにはハッシュ セットを使用する必要があるため、時間計算量は O(m+n)、空間計算量は O(m) になります。リストヘッドA.

ただし、タイトルには O(1) の空間計算量が必要であるため、この変更方法は要件を満たしていません。

3. 二点法:ロマンチックな出会いは美しすぎる

アルゴリズムリファレンス:グラフィカルダブルポインター法、ロマンチックな出会い

3.1 アルゴリズムのアイデア

2 つの連結リストの長さはそれぞれ L1+C と L2+C で、C は共通部分の長さです。

1人目がL1+C歩を歩いた後、2人目のスタート地点に戻ってL2歩、2人目がL2+C歩を歩いた後、1人目のスタート地点に戻ってL1歩を歩きます。二人の歩数がL1+L2+Cのとき、二人は出会う

3.2 コード

主なコード:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        pt1=headA
        pt2=headB
        while pt1!=pt2:
            if pt1:
                pt1=pt1.next
            else:
                pt1=headB
            
            if pt2:
                pt2=pt2.next
            else:
                pt2=headA
        return pt1

高度なコード:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        pt1=headA
        pt2=headB
        while pt1!=pt2:
            pt1=pt1.next if pt1 else headB
            pt2=pt2.next if pt2 else headA
        return pt1

この 2 点法は美しすぎますが、このような美しい方法はどのくらい難しいのでしょうか? ? ?

おすすめ

転載: blog.csdn.net/qq_43799400/article/details/131559288