記事ディレクトリ
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 点法は美しすぎますが、このような美しい方法はどのくらい難しいのでしょうか? ? ?