「代码随想录」Python刷题笔记Day4-链表专题

链表第二天

    • 24. 两两交换链表中的节点
    • 19.删除链表的倒数第N个节点
    • 面试题 02.07. 链表相交
    • 142.环形链表II

24. 两两交换链表中的节点

链接
leetcode-24

题目
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)
「代码随想录」Python刷题笔记Day4-链表专题_第1张图片

class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        dummy_head = ListNode(next=head)
        current = dummy_head
        
        # 必须有cur的下一个和下下个才能交换,否则说明已经交换结束了
        while current.next and current.next.next:
            temp = current.next # 防止节点修改
            temp1 = current.next.next.next
            
            current.next = current.next.next
            current.next.next = temp
            temp.next = temp1
            current = current.next.next
        return dummy_head.next

19.删除链表的倒数第N个节点

链接
leetcode-19

题目
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
「代码随想录」Python刷题笔记Day4-链表专题_第2张图片
一开始想过采用两次循环,先计数,再尝试用之前题目中写过的删除index的方式进行删除。但是总是会在边界情况处理不好。
贴上一个不正确的答案,只能过190/208(这就是我在考场上能写出的样子吧……)

class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        dummyNode = ListNode(next=head)
        size = 0
        
        current = dummyNode.next
        while current.next:
            current = current.next
            size += 1

        if n<0 or n>size+1 or size==0:
            return 
        
        current = dummyNode.next
        for i in range(size-n):
            current = current.next
        current.next = current.next.next

        return dummyNode.next

学习采用快慢指针的方法解决该问题。
可以参考labuladong的双指针技巧秒杀七道链表题目

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        # 创建一个虚拟节点,并将其下一个指针设置为链表的头部
        dummy_head = ListNode(0, head)
        # 创建两个指针,慢指针和快指针,并将它们初始化为虚拟节点
        slow = fast = dummy_head
        
        # 快指针比慢指针快 n+1 步
        for i in range(n+1):
            fast = fast.next
        
        # 快指针到达链表的末尾时,循环结束
        while fast:
            slow = slow.next
            fast = fast.next
        
        # 通过更新第 (n-1) 个节点的 next 指针删除第 n 个节点
        slow.next = slow.next.next
        
        return dummy_head.next

面试题 02.07. 链表相交

链接
leetcode-160

题目
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
「代码随想录」Python刷题笔记Day4-链表专题_第3张图片
「代码随想录」Python刷题笔记Day4-链表专题_第4张图片

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        lenA, lenB = 0, 0
        cur = headA
        while cur:
            cur = cur.next 
            lenA += 1
        cur = headB 
        while cur:
            cur = cur.next 
            lenB += 1
        curA, curB = headA, headB
        if lenA > lenB:
            curA, curB = curB, curA
            lenA, lenB = lenB, lenA 
        for i in range(lenB - lenA):
            curB = curB.next 
        while curA:
            if curA == curB:
                return curA
            else:
                curA = curA.next 
                curB = curB.next
        return None 

142.环形链表II

链接
leetcode-142

题目
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

def detectCycle(head: ListNode) -> ListNode:
    fast = slow = head
    # 快指针走两步,慢指针走一步
    # 如果快指针追上了慢指针,说明有环
    while fast and fast.next:
        fast = fast.next.next
        slow = slow.next
        if fast == slow:
            break 
    # 否则,没有环
    if not fast or not fast.next:
        return None
    # 判断开始入环的第一个节点
    slow = head 
    while slow != fast:
        fast = fast.next
        slow = slow.next
    return slow

判断环起点的思路详见142.环形链表II
需要整理!

另外,运用集合,使得这道题目的难度瞬间降低了一个级别:

# 集合法
class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        visited = set()
        while head:
            if head in visited:
                return head
            visited.add(head)
            head = head.next
        return None

你可能感兴趣的:(代码随想录,链表,python,笔记)