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

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

解题:

关键:

  1. cur的位置在要交换的两个节点的前面
  2. 具体如何交换的操作!!
  3. while种植条件:cur的下一个和下下个都不为空,不能写反不然会空指针异常,用and不是or
  4. 同样用虚拟头节点
点击查看代码
class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        dummyhead=ListNode(next=head)
        cur=dummyhead
        while cur.next and cur.next.next:
            tmp=cur.next
            tmp1=cur.next.next.next
            cur.next=cur.next.next
            cur.next.next=tmp
            tmp.next=tmp1
            cur=cur.next.next
        return dummyhead.next

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

题目:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

解题:

思路:链表不知道总长度,所以要用快慢双指针的移动来找到删除的节点。
关键:

  1. fast比slow快n+1步
  2. 终止条件:fast指向Null
点击查看代码
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        dummyhead=ListNode(next=head)
        slow=dummyhead
        fast=dummyhead
        for i in range(n+1):
            fast=fast.next
        while fast:
            slow=slow.next
            fast=fast.next
        slow.next=slow.next.next
        return dummyhead.next

面试题 02.07. 链表相交

题目:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:

题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。

解题:

思路:

  1. 求出两链表的长度;
  2. 确定哪个链表长,让cur1表示短链表,cur2表示长链表;
  3. 长cur2移动到和短cur1长度一样的位置处(末尾对齐),即同时移动(len2-len1)步;
  4. 用while同时向后移动cur1和cur2,如何指向同一个节点就返回节点。注意:判断句if cur1==cur2表示是否指向一个节点,而不是判断val值。
点击查看代码
class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        lenA,lenB=0,0
        curA=headA
        while curA:
            lenA+=1
            curA=curA.next
        curB=headB
        while curB:
            lenB+=1
            curB=curB.next
        cur1,cur2=headA,headB
        if lenA>lenB: #cur1短,cur2长
            cur1,cur2=cur2,cur1
            len1,len2=lenB,lenA
        else:
            len1,len2=lenA,lenB
        for i in range(len2-len1):
            cur2=cur2.next
        while cur1:
            if cur1==cur2:
                return cur1
            else:
                cur1=cur1.next
                cur2=cur2.next
        return None

142.环形链表II

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

解题:

思路:数学问题。快慢指针,fast每次移动2个节点,slow每次移动1个节点。
两个要点:
一、判断是否有环:fast和slow有相遇,说明有环。
二、找到环的入口:先走到fast和slow相遇点,然后让index1=fast和index2=head同时移动直到两者相遇,就是入口处。
相遇时,slow走的节点数:x+y,fast走的节点数:x+y+n(y+z)。构建等式可以知道x=z。

点击查看代码
class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        fast=head
        slow=head
        while fast and fast.next:
            fast=fast.next.next
            slow=slow.next
            if fast==slow:
                index1=fast
                index2=head
                while index1!=index2:
                    index1=index1.next
                    index2=index2.next
                return index1
        return None

心得:

当在删除、交换等操作中,为了统一处理头结点和其他节点的规则时,需要使用虚拟头节点
画图理清思路很重要

posted @   Y荷兰豆Y  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示