Day 4 | 24. 兩兩交換連結串列中的節點 、 19.刪除連結串列的倒數第N個節點 、面試題 02.07. 連結串列相交 、142.環形連結串列II

forrestr發表於2024-05-25

24. 兩兩交換連結串列中的節點

用虛擬頭結點,這樣會方便很多。

本題連結串列操作就比較複雜了,建議大家先看影片,影片裡我講解了注意事項,為什麼需要temp儲存臨時節點。

題目連結/文章講解/影片講解: https://programmercarl.com/0024.兩兩交換連結串列中的節點.html

思考

需要設定一個虛擬頭節點,方便操作。
最好先畫下圖,明確指標斷開重連的步驟,哪些節點需要用臨時變數存起來。

class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        dummy = ListNode()
        dummy.next = head
        cur = dummy
        while cur.next and cur.next.next:
            temp = cur.next
            temp1 = cur.next.next.next
            cur.next = cur.next.next
            cur.next.next = temp
            temp.next = temp1
            cur = temp
        return dummy.next

19.刪除連結串列的倒數第N個節點

雙指標的操作,要注意,刪除第N個節點,那麼我們當前遍歷的指標一定要指向 第N個節點的前一個節點,建議先看影片。

題目連結/文章講解/影片講解:https://programmercarl.com/0019.刪除連結串列的倒數第N個節點.html

思考

設定一個虛擬頭結點,方便只有一個節點時進行操作。雙指標,間隔n-1步,正好可以取到倒數第n個節點的前一個節點,方便刪除。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        dummp = ListNode(0)
        dummp.next = head
        fast = dummp
        slow = dummp
        i = 0
        while fast:
            fast = fast.next
            if i > n:
                slow = slow.next
            i+=1
        slow.next = slow.next.next
        return dummp.next

面試題 02.07. 連結串列相交

本題沒有影片講解,大家注意 數值相同,不代表指標相同。

題目連結/文章講解:https://programmercarl.com/面試題02.07.連結串列相交.html

思考

A遍歷完後,接著遍歷B。B遍歷完後,接著遍歷A。
相交的時候,正好兩種路徑走的步長一樣。

# 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:
        curA = headA
        curB = headB
        is_A = True
        is_B = True
        while curA and curB:
            if curA == curB:
                return curA
            if curA.next is None and is_A:
                curA = headB
                is_A = False
            else:
                curA = curA.next
            if curB.next is None and is_B:
                curB = headA
                is_B = False
            else:
                curB = curB.next
        return None

上面的程式碼太冗餘了,實際上while的條件直接判斷curA和curB是否相等就好了,如果相交,則在交點退出,如果不想交,正好在連結末尾退出。

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

142.環形連結串列II

算是連結串列比較有難度的題目,需要多花點時間理解 確定環和找環入口,建議先看影片。

題目連結/文章講解/影片講解:https://programmercarl.com/0142.環形連結串列II.html

思考

快慢指標,慢指標速度是1,快指標速度是2,速度差是1,如果有環,一定會在環內相遇。

x和z的關係如下,
x = (n - 1) (y + z) + z
在相遇點和頭結點同時遍歷的話,一定會在入口處再次相遇。(從相遇點出發的遍歷可能會多跑n-1圈)

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

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow = head
        fast = head
        while True:
            
            if fast and fast.next:
                fast = fast.next.next
            else:
                return None
            slow = slow.next
            if slow == fast:
                break
        # 相交
        new_slow = head
        while new_slow != slow:
            new_slow = new_slow.next
            slow = slow.next
        return slow

相關文章