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

文章讲述了作者在学习和解决链表问题时的经历,包括如何处理链表的两两交换、判断链表节点的奇偶性,以及删除链表倒数第n个节点和检测环形链表的方法。作者分享了解题过程中的关键步骤和代码片段,以及对算法的理解和改进过程。
摘要由CSDN通过智能技术生成

我基础比较差,时间又紧张,努力过后发现群里的打卡进度还是跟不上了。。没关系,我按自己的节奏先刷完第一遍!!!

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

直接看了题解视频:https://www.bilibili.com/video/BV1YT411g7br/?vd_source=40781b3117fa72cc67da258629107b62

有个一开始没先到的条件判断是链表为奇数还是偶数个。

看完直接写的结果是这样的,没有通过。对照答案之后发现temp1少些了一个.next,最后一步cur移位也少写了一个.next(只移了一位,应该要移两位)

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution(object):
    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        dummyhead = ListNode()
        dummyhead.next = head
        cur = dummyhead
        while cur.next != None and cur.next.next != None:
            temp=cur.next
            temp1 = cur.next.next
            cur.next = cur.next.next
            cur.next.next = temp
            cur.next.next.next = temp1
            cur=cur.next
        return dummyhead.next
        

修改后通过了!这是我目前做过通过最快的一道题了!

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution(object):
    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        dummyhead = ListNode()
        dummyhead.next = head
        cur = dummyhead
        while cur.next and cur.next.next:
            temp=cur.next
            temp1 = cur.next.next.next
            cur.next = cur.next.next
            cur.next.next = temp
            cur.next.next.next = temp1
            cur=cur.next.next
        return dummyhead.next

在答案里看到了迭代解法,决定尝试一下,感觉递归那一步好巧妙。

class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if head is None or head.next is None:
            return head

        # 待翻转的两个node分别是pre和cur
        pre = head
        cur = head.next
        next = head.next.next
        
        cur.next = pre  # 交换
        pre.next = self.swapPairs(next) # 将以next为head的后续链表两两交换
         
        return cur

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

直接看讲解视频了:https://www.bilibili.com/video/BV1vW4y1U7Gf/

感觉用双指针的方法来找到倒数第n个节点好巧妙!问题是,怎么构造快指针比慢指针快n+1步呢?感觉这是个经常遇到的问题,我去看了答案,发现是用for循环的range的范围实现的,以后可以用起来!

第一次写成了这样,发现没有通过。查看答案之后发现应该return dummyhead.next而不是head,有道理啊,万一链表只有1个节点,head被删掉了咋办。

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution(object):
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        dummyhead = ListNode(next=head)
        fast=dummyhead
        slow=dummyhead

        for i in range(n+1):
            fast = fast.next
        
        while fast:
            fast = fast.next
            slow = slow.next
        
        slow.next = slow.next.next
        return head

于是重新修改后提交,通过了!这道题也很快,中间遇到的问题不太多。

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution(object):
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        dummyhead = ListNode(next=head)
        fast=dummyhead
        slow=dummyhead

        for i in range(n+1):
            fast = fast.next
        
        while fast:
            fast = fast.next
            slow = slow.next
        
        slow.next = slow.next.next
        return dummyhead.next

02.07 链表相交

leetcode链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/

这道题居然没有视频讲解。。我看题之后感觉一个难点是,两个链表不能同时从头节点开始遍历,因为相交之前的部分很可能不一样长。题解里说,交点不是数值相等,而是指针相等,看了三遍之后,我还是觉得半懂不懂,指的是val和next都要相等吗?

决定直接看答案了。原来还是有点复杂的。这题恐怕我得背一下。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        lenA, lenB = 0, 0
        cur = headA
        while cur:         # 求链表A的长度
            cur = cur.next 
            lenA += 1
        cur = headB 
        while cur:         # 求链表B的长度
            cur = cur.next 
            lenB += 1
        curA, curB = headA, headB
        if lenA > lenB:     # 让curB为最长链表的头,lenB为其长度
            curA, curB = curB, curA
            lenA, lenB = lenB, lenA 
        for _ in range(lenB - lenA):  # 让curA和curB在同一起点上(末尾位置对齐)
            curB = curB.next 
        while curA:         #  遍历curA 和 curB,遇到相同则直接返回
            if curA == curB:
                return curA
            else:
                curA = curA.next 
                curB = curB.next
        return None 

后面还有一个把其中一些步骤封装成函数的写法,感觉清晰一些。首先是要链表的尾部拽齐了,把两个指针定位从后数长度一致的那个位置,然后开始往后遍历,直到找到相等的指针(交点)。

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        # 计算两个链表的长度差
        dis = self.getLength(headA) - self.getLength(headB)
        
        # 通过移动较长的链表,使两链表长度相等
        if dis > 0:
            headA = self.moveForward(headA, dis)  # 移动链表A的头指针使其与链表B长度相等
        else:
            headB = self.moveForward(headB, abs(dis))  # 移动链表B的头指针使其与链表A长度相等
        
        # 将两个头指针向前移动,直到它们相交
        while headA and headB:
            if headA == headB:  # 如果两个指针相等,表示找到了相交点
                return headA
            headA = headA.next  # 向前移动链表A的头指针
            headB = headB.next  # 向前移动链表B的头指针
        
        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

142.环形链表Ⅱ

据说这个题比较复杂。力扣链接在这里:https://leetcode.cn/problems/linked-list-cycle-ii/description/

直接看讲解了:https://www.bilibili.com/video/BV1if4y1d7ob/?vd_source=40781b3117fa72cc67da258629107b62

确实难,我理了一下,需要先找到相遇节点,再找环的入口。这个题感觉也是需要背一下。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        slow = head
        fast = head
        
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            
            # If there is a cycle, the slow and fast pointers will eventually meet
            if slow == fast:
                # Move one of the pointers back to the start of the list
                slow = head
                while slow != fast:
                    slow = slow.next
                    fast = fast.next
                return slow
        # If there is no cycle, return None
        return None

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值