代码随想录算法训练营第四天|24. 两两交换链表中的节点、19. 删除链表的倒数第N个节点、面试题 02.07. 链表相交、142. 环形链表II

72 阅读4分钟

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

题目描述:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

题目链接:leetcode.cn/problems/sw…

解题思路:

  1. 显然要用双指针。
  2. 为了单独判断头节点所以使用dummy头节点。
  3. 先动手画出交换过程,再敲代码。
  4. 交换过程:
    (1)初始化双指针。pre指向dummycur指向head
    (2)用中间指针temp储存pre.next.next
    (3)pre.next = cur.next
    (4)cur.next = temp.next
    (5)temp.next = cur
    (6)pre = pre.next.next

扫描全能王 2023-01-15 16.54_1.jpg

代码:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head:
            return 

        dummy = ListNode(next=head)
        pre = dummy

        while pre.next and pre.next.next:
            cur = pre.next
            tmp = cur.next

            pre.next = cur.next
            cur.next = tmp.next
            tmp.next = cur

            pre = pre.next.next
        
        return dummy.next

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

题目描述:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。尝试使用一趟扫描实现。

题目链接:leetcode.cn/problems/re…

解题思路:

  1. 为了不单独判断头节点,需要使用虚拟头节点dummy
  2. 一趟扫描的实现方法:双指针。
  3. 初始化fastslow指针,两个指针均指向dummyfast指针先向前走n个结点,此时fastslow指针一起向前遍历,当fast指针指向最后一个节点时,slow指针指向倒数第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]:
        dummy = ListNode(next=head)
        fast = slow = dummy
        while n:
            fast = fast.next
            n -= 1
        
        while fast.next:
            slow = slow.next
            fast = fast.next
        
        slow.next = slow.next.next
        return dummy.next

面试题 02.07. 链表相交

题目描述:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。题目数据 保证 整个链式结构中不存在环。注意,函数返回结果后,链表必须 保持其原始结构 。

题目链接:leetcode.cn/problems/in…

解题思路:

  1. 设头节点headA所在链表为A链表,头节点headB所在链表为B链表,A链表从headA到与B链表相交起始节点前的长度为aB链表从headB到与A链表相交起始节点前的长度为bAB链表相交节点的长度为c
  2. 初始化指针p指向headAq指向headB
  3. pq两指针没有指向同一节点时,pheadA出发开始遍历链表A,遍历完A链表就从headB开始遍历B链表,qheadB出发开始遍历链表B,遍历完B链表就从headA开始遍历A链表。则p走过的节点长度为:a+c+bq走过的节点长度为:b+c+a。很明显a+c+b=b+c+a,即当pq遍历过的节点数相等时,两个指针指向的同一节点是相交节点。

代码:

# 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:
        if not headA or not headB:
            return 
        
        A, B = headA, headB

        while A != B:
            A = A.next if A else headB
            B = B.next if B else headA
        
        return A

142. 环形链表II

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

题目链接:leetcode.cn/problems/li…

解题思路:

  1. 使用快慢指针。fast每次走两个节点,slow每次走一个节点。
  2. 初始化指针fast、slow指向head。设从head起到环入口节点之间的节点数为x,环入口节点到两指针相遇处的节点之间的节点数为y,从相遇节点再到环入口处之间的节点数为z。很明显,fast走过的节点数 = slow走过的节点数 * 2。
  3. x + y + n * (y + z) =(x + y)* 2。n为fast指针在环内走了n圈才遇到slow指针, (y + z)为一圈内节点的个数A。
  4. 化简得:x = (n - 1) * (y + z) + z。当n = 1时,x = z。即,当fast、slow相遇时,初始化指针p指向head,指针q指向相遇节点,p、q开始遍历,当p和q指向同一节点时,此节点为链表开始入环的第一个节点。

image.png

代码:


# 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]:
        if not head:
            return 
        fast = slow = head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            if fast == slow:
                p = fast
                q = head
                while p != q:
                    p, q = p.next, q.next
                return p
        
        return None