2023/7/15--代码随想录算法训练营day4|24.两两交换链表节点、19.删除倒数第N个节点、142.环形链表

文章介绍了几种链表操作的解题思路,包括两两交换链表节点,删除链表的倒数第N个节点,以及寻找两个链表的相交节点。这些操作都利用了双指针技巧,如快慢指针和虚拟头结点,以解决链表问题。对于环形链表的检测,文章提到了快慢指针和集合两种方法。
摘要由CSDN通过智能技术生成

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

状态】:这道题一定要画个图,而且确定循环里面,cur到底传给谁很重要。然后循环条件,cur.next和cur.next.next都要不为空。最后自己磕磕绊绊,看了思路也写出来了,还需要多练习!!【如果想要改动当前节点,把指针就放在上一个节点,调用next】
题目:在这里插入图片描述

思路: 涉及到局部动头结点,需要立马想到dummy_head虚拟头结点
在这里插入图片描述

class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        dummy_head = ListNode(next=head)
        current = dummy_head
        
        # 必须有cur的下一个和下下个才能交换,否则说明已经交换结束了【要回判断终止情况!!!!】
        while current.next and current.next.next:  #一个next控制偶数情况,两个next控制奇数节点情况
        #!!!!一定要先判断next为空,然后在判断next.next为空,否则如果next为空,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个节点

【状态】:

  1. 在写的时候,因为可能会删掉头结点,所以我里面考虑使用虚拟头结点
  2. 但是这一题,与构造链表不一样的是,没有self.size返回链表的有效节点数。看了题目思路,快慢指针,让快指针先走n步,快指针走到末尾,慢指针刚好就在倒数n个位置上。
  3. 删除某个节点,跑到这个要删节点的前面,操作!

题目:
在这里插入图片描述
思路双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。

  1. fast指针和slow指针:开始都指向虚拟头结点
  2. fast先走,然后两个指针一起走,直至fast指针指向末尾
  3. 删除slow指针指向的下一个节点
    时间复杂度 O(n) ,空间复杂度O(1)
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 链表相交

【状态】:

  1. 刚开始没思路,看了思路以后,去写了代码;然后代码超时,估计哪里(调用函数self方法)写错了,很重要的是,是让两个链表的指针一样的时候返回,不是值一样的时候返回
  2. 然后我又去看了一遍代码,尝试着自己写,又因为while循环的边界条件没理清楚,出现报错。

【题目】
在这里插入图片描述
【思路】
1.类似于那个倒数第n个节点的想法。(快指针先走n步,然后慢指针走)
链表A的长度-链表B的长度然后让多出来的那部分先走,然后在一起走(这样确保末位对齐)。最后在headA和headB指针一样,返回指针就行。
注意:
1.while循环结束的临界点
2.类里面的方法调用 self.函数名
3.两个链表指针一样,才返回,不是数值

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        lenA = self.getLength(headA)
        lenB = self.getLength(headB)
        
        # 通过移动较长的链表,使两链表长度相等
        if lenA > lenB:
            headA = self.moveForward(headA, lenA - lenB)
        else:
            headB = self.moveForward(headB, lenB - lenA)
        
        # 将两个头向前移动,直到它们相交
        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:
            length += 1
            head = head.next
        return length
    
    def moveForward(self, head: ListNode, steps: int) -> ListNode:
        while steps > 0:
            head = head.next
            steps -= 1
        return head

2.等比例法:这个方法很巧妙
在这里插入图片描述
链表的长度,当两个链表都跑a+b+c这个长度,肯定会在交点/终点null相遇。

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if not headA or not headB:# 处理边缘情况
            return None
        
        # 在每个链表的头部初始化两个指针
        pointerA = headA
        pointerB = headB
        
        # 遍历两个链表直到指针相交
        while pointerA != pointerB:
            # 将指针向前移动一个节点
            pointerA = pointerA.next if pointerA else headB
            pointerB = pointerB.next if pointerB else headA
        
        # 如果相交,指针将位于交点节点,如果没有交点,值为None
        return pointerA

142. 环形链表

【状态】自己写没写出来,看了思路和代码,才把题目写出来。
【题目】
【思路】
1.快慢指针
(1)用快指针(两倍速)和慢指针(一倍数)跑,如果有环,找到相遇节点。(2)然后一个指针从相遇节点走,一个指针从头结点走,直至指针相同,返回。【如果三倍速跑,快指针相对于慢指针一次跳两步,有可能越过慢指针,可能永远错过!在这里插入图片描述

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        slow = head
        fast = head
        
        while fast and fast.next:   #注意循环临界条件,要不然fast.next.next不得报错
            slow = slow.next
            fast = fast.next.next  #null是没有next
           
            if slow == fast:  #这个时候说肯定是有环的,fast=slow=相遇节点
                slow = head  #一个节点指向头结点
                while slow != fast:
                    slow = slow.next
                    fast = fast.next
                return slow   #返回相交节点
        #while执行完,
        return None

2.集合法集合.add(元素)

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值