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

本文详细介绍了四种常见的链表操作问题:两两交换链表中的节点、删除链表的倒数第N个节点、查找链表相交的节点以及环形链表II。对于每种问题,作者提供了解题思路、代码实现以及优化方法。通过这些实例,读者可以深入理解链表操作的基本技巧,包括快慢指针、单遍历解决方案等。
摘要由CSDN通过智能技术生成

一、今日任务

二、 两两交换链表中的节点

2.1 题目:24. 两两交换链表中的节点

2.2 解题过程

简单的模拟题目。

遇到的问题是交换之后head.next没有更新导致失去了部分节点,这也是提示用虚拟头结点的原因。

代码如下

class Solution(object):
    # 简单模拟 虚拟头结点非常重要。以及NULL or 1 个节点的链表要单独讨论
    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        NewHead = ListNode()
        NewHead.next = head
        if head == None or head.next == None:
            return head
        else:
            ppre = NewHead ##important
            pre = head
            cur = head.next
            while cur != None:
                temp = cur.next
                cur.next = pre
                pre.next = temp
                ppre.next = cur ## important
                if temp == None or temp.next == None:
                    break
                else:
                    ppre = pre ## important
                    pre = temp
                    cur = temp.next
            return NewHead.next

毫不意外,超时。

也看到了建议在O(n)的时间复杂度里解出来。

其实可以看做一个非有序的数组进行排序。只要找到O(n)的排序方法就行。

这是想到了归并排序。只要找到分段处就可以执行。

代码如下:

def sortedSquares1(self, nums):
    """
    :type nums: List[int]
    :rtype: List[int]
    """
    NewNums = []
    flag = -1
    for i in range(0, len(nums)):
        if nums[i] < 0:
            flag = i
        nums[i] = nums[i] * nums[i]
    if flag == -1:
        return nums
    else:
        n = flag
        p = flag + 1
        i = 0
        while n >= 0 and p < len(nums):
            if nums[n] < nums[p]:
                NewNums.append(nums[n])
                n -= 1
            else:
                NewNums.append(nums[p])
                p += 1
            i += 1
        while i < len(nums) and n >= 0:
            NewNums.append(nums[n])
            n -= 1
            i += 1
        while i < len(nums) and p < len(nums):
            NewNums.append(nums[p])
            p += 1
            i += 1
    return NewNums

2.3 阅读材料改进

文章中的代码显得简洁很多。但思路大体一致。

以下是复现代码:

# 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
        """
        NewHead = ListNode(next = head)
        cur = NewHead

        while cur.next and cur.next.next:
            pre = cur 
            cur = cur.next
            post = cur.next
            temp = cur.next.next
            
            pre.next = post
            post.next = cur
            cur.next = temp

            cur = pre.next.next

        return NewHead.next
    


三、删除链表的倒数第 N 个结点

3.1 题目:19. 删除链表的倒数第 N 个结点

3.2 解题过程

拿到这一题,第一反应就是要第一遍遍历计算链表长度,第二遍遍历定位删除。遇到一个问题,每次都想要直接返回head,但是忘记head节点不一定是头结点了。

class Solution(object):
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        newheadFsize = ListNode(next = head)
        newheadFdelete = ListNode(next=head)
        NewHead =newheadFdelete
        size = 0
        while newheadFsize.next:
            size += 1
            newheadFsize = newheadFsize.next
        index = size - n
        while newheadFdelete.next:
            if index == 0:
                newheadFdelete.next = newheadFdelete.next.next
                break
            index -= 1
            newheadFdelete = newheadFdelete.next
        return NewHead.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 removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        newheadFdelete = ListNode(next=head)
        NewHead =newheadFdelete
        prev = NewHead
        post = NewHead
        while post.next:
            if n:
                post = post.next
                n -= 1
            else:
                post = post.next
                prev = prev.next
        prev.next = prev.next.next
        return newheadFdelete.next

3.3 阅读材料改进

第二个版本的代码与随想录里思路一致。开心!

显然会比一个while,彻底解决自己得一个很大的问题。

四 、面试题 02.07. 链表相交

4.1 题目:面试题 02.07. 链表相交

4.2 解题过程

看第一遍题目的时候还是有点茫然,有点不知所措。

老规矩,先暴力解,再考虑优化问题。果不其然超时41/45

# 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
        """
        NewHeadA = ListNode(next = headA)
        NewHeadB = ListNode(next = headB)
        A = NewHeadA
        B = NewHeadB
        
        while A.next:
            while B.next:
                if A.next == B.next:
                    return A.next
                B = B.next
            B = NewHeadB
            A = A.next
        return None

时间复杂度要求O(n),那么就一定是要只有一边遍历,验证节点相同的条件就是 A==B。这时想到的是分别反转链表,再同时反转遍历。这样时间复杂度就为O(n+m+x)

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

class Solution(object):
    def ListReverse(self, head):
        Newhead  = ListNode(next = head)
        newhead  = ListNode(next = head)
        prev = newhead.next
        post = newhead.next.next
        while post:
            temp = post.next
            post.next = newhead.next
            prev.next = temp
            newhead.next = post

            post = temp   
        return newhead



    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        RA = self.ListReverse(headA)
        RB = self.ListReverse(headB)
        while RA.next and RB.next:
            if RA.next == RB.next:
                return RA.next
            RA = RA.next
            RB = RB.next
        return None

千辛万苦做好,发现不允许修改链表结构。

灰心丧气去看了解答。

4.3 阅读材料改进

很简单的算法呀,怎么就没想到!!找到较长的链表,将其指针移到和短链表同一起点,一一对应比较!

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        NewHeadA = ListNode(next=headA)
        NewHeadB = ListNode(next=headB)
        headFsizeA = NewHeadA
        headFsizeB = NewHeadB
        lengthA = 0
        lengthB = 0
        while headFsizeA.next:
            headFsizeA = headFsizeA.next
            lengthA += 1
        while headFsizeB.next:
            headFsizeB = headFsizeB.next
            lengthB += 1

        if lengthA > lengthB:
            longer = lengthA
            shorter = lengthB
            shorterhead = NewHeadB
            longerhead = NewHeadA
        else:
            longer = lengthB
            shorter = lengthA
            shorterhead = NewHeadA
            longerhead = NewHeadB
        discrepancy = longer - shorter
        while discrepancy:
            longerhead = longerhead.next
            discrepancy -= 1
        while longerhead.next:
            if longerhead.next == shorterhead.next:
                return longerhead.next
            longerhead = longerhead.next
            shorterhead = shorterhead.next
        return None

五、142. 环形链表II

5.1 题目:142. 环形链表 II

5.2 解题过程

目前来说,最简单暴力的方法就是遍历存储,出现第一个相等的结点就是。

暴力解法如下:

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        newhead = ListNode(next = head)
        cur = newhead
        nodelist = []
        while cur.next:
            for i in nodelist:
                if i == cur.next:
                    return i
            nodelist.append(cur.next)
            cur = cur.next
        return None

力扣进阶要求是使用O(1)的空间复杂度。遍历一圈,寻找哪两个next相等。这个方法显然不行,因为根本没有条件遍历,是一个环只会无穷循环。实在想不出。看随想录吧。

5.3 阅读材料改进

思考方向一定是快慢指针,但是没想到其中的涉及到能够相遇。

思路是,先判断有环,再判断入口。

理论知识有点混乱,今天就先不复现了。

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        slow, fast = head, head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            # 如果相遇
            if slow == fast:
                p = head
                q = slow
                while p!=q:
                    p = p.next
                    q = q.next
                #你也可以return q
                return p

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值