代码随想录算法训练营第四天(链表篇)|Leetcode24两两交换链表节点,Leetcode19删除倒数第n个节点,链表相交,环形链表

Leetcode 24 两两交换链表节点

题目链接: 两两交换链表节点
给定一个链表,要求两两交换其节点,最后返回其处理完成后的头节点。
1->3->2->4->5,处理后得到3->1->4->2->5

思路:
本题重点还是明确链表操作过程中,每一步做了什么操作。详情见下图。
在操作链表节点的场景中,只需要明确每一步完成了什么操作,注意及时保存更新节点即可。
此处引入虚拟头节点是为了方便处理实际头节点。

两两交换链表节点24

具体代码实现

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

时间复杂度: O(n)

Leetcode 19 删除倒数第n个节点

题目链接: 删除倒数第n个节点

给定一个链表,要求删除其倒数第n个节点。
1->2->3->5->4,删除倒数第2个节点后得到1->2->3->4

思路:
在单向链表中,若希望删除一个节点,则首先需要找出其前一个节点,随后修改其前一个节点指针的指向以完成删除操作(视语言的不同需要手动释放内存)。此处要删掉倒数第n个节点,自然需要找出倒数第n个节点的前一个节点。为此,我们可以采用双指针法。让快指针领先慢指针n个单位,这样当快指针移动到链表末尾时,慢指针正好移动到倒数第n个节点的前一个节点。

具体代码实现

class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        dummyHead = ListNode(0, head)
        slow, fast = dummyHead, dummyHead
        while n:
            fast = fast.next
            n-=1
        while fast.next:
            fast = fast.next
            slow = slow.next
        slow.next = slow.next.next
        return dummyHead.next

时间复杂度: O(n)

链表相交

题目链接: 链表相交

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

思路: 若希望判断两个单链表相交,最直观的方式为,在遍历两个链表时,同时遍历到同一个节点,则能够说明两个链表存在交点。而给出的两个单链表的长度不一致,因此,我们自然想到需要转化问题: 若两个单链表长度一致,同时从头遍历,就一定能够找出相交的起始节点。我们先统计两个单链表的长度,在截长后同时遍历即可。

具体代码实现:

class ListNode:
    def __init__(self, val=0, next=None) -> None:
        self.val = val
        self.next = next

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        curA, curB = headA, headB
        lengthA, lengthB = self.getLength(curA), self.getLength(curB)

        diff = abs(lengthA - lengthB)
        if lengthA < lengthB:
            headA, headB = headB, headA

        for _ in range(diff):
            headA = headA.next

        while headA and headB:
            if headA == headB:
                return headA
            headA = headA.next
            headB = headB.next

        return None

    def getLength(self, head: ListNode) -> int:
        length = 0
        while head:
            head = head.next
            length += 1
        return length

时间复杂度: O(n)

Leetcode 142 环形链表

题目链接: 环形链表

给定一个单链表,判断链表中是否成环,若成环则返回环的入口节点。

思路: 本题需要综合结合链表性质和数学知识求解。
首先,我们需要判断链表是否成环;若成环,我们需要找出入口节点。

对于第一个问题,我们可以通过快慢指针的方式,判断是否成环。类似操场跑步时的“套圈”,在环形跑道中,快速跑者一定会与慢速跑者相遇。同理,遍历链表,若快慢指针最终相遇,则说明存在环;否则不存在环。
对于第二个问题,我们不妨画图列方程辅助理解:

假设从链表入口位置到环入口节点位置之间的举例为n,慢指针在快指针在环内转了t圈后,与快指针相遇,从环入口节点到快慢指针相遇的位置距离为x,从相遇位置出发回到环入口节点距离为y。快指针速度为慢指针的2倍。

则有: n+t(x+y)+x = 2(n+x),即(t-1)x+ty = n,令t=1,则有y=n。即两个指针相遇的位置和链表起始位置,到环起始处的距离相同。

判断链表是否成环142

具体代码实现

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow, fast = head, 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
        while head != slow:
            head = head.next
            slow = slow.next
        return slow
posted @ 2025-08-09 14:55  雪痕春风天音九重色  阅读(40)  评论(0)    收藏  举报