【日常系列】LeetCode《14·链表1》

数据规模->时间复杂度

<=10^4 😮(n^2)
<=10^7:o(nlogn)
<=10^8:o(n)
10^8<=:o(logn),o(1)

整体内容

在这里插入图片描述

lc 203 :移除链表元素
https://leetcode.cn/problems/remove-linked-list-elements/
提示:
列表中的节点数目在范围 [0, 104] 内
1 <= Node.val <= 50
0 <= val <= 50
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

#方案一:删除表头元素与非表头元素
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        #删表头
        while head!=None and head.val==val:
            delnode=head #key
            head=head.next
            delnode.next=None

        #删表中
        if head==None:return None #key:head是指向第一个元素的,若此时为None,则没有next属性
        prev=head
        curr=head.next
        while curr:
            if curr.val==val:
                prev.next=curr.next
                curr.next=None
                curr=prev.next
            else:
                prev=curr
                curr=curr.next
        return head
        
#方案二:虚拟节点统一删除逻辑
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        #建虚拟节点
        dummynode=ListNode(-1)
        dummynode.next=head
        #统一删除逻辑
        prev=dummynode
        curr=head
        while curr:
            if curr.val==val:
                prev.next=curr.next
                curr.next=None
                curr=prev.next
            else:
                prev=curr
                curr=curr.next
        return dummynode.next

在这里插入图片描述

lc 237 删除链表中的节点
https://leetcode.cn/problems/delete-node-in-a-linked-list/
提示:
链表中节点的数目范围是 [2, 1000]
-1000 <= Node.val <= 1000
链表中每个节点的值都是 唯一 的
需要删除的节点 node 是 链表中的节点 ,且 不是末尾节点

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

class Solution:
    def deleteNode(self, node):
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        """
        while node:
            nextnode=node.next
            if nextnode:
                node.val=nextnode.val        
            else:
                prev.next=None
            #注:位置
            prev=node
            node=node.next       
             
#方案二:
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def deleteNode(self, node):
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        """
        #
        node.val=node.next.val
        #
        nextN=node.next #注:标记
        node.next=nextN.next
        nextN.next=None #node.next.next=None会报错       

lc 83 :删除排序链表中的重复元素
https://leetcode.cn/problems/remove-duplicates-from-sorted-list/
提示:
链表中节点数目在范围 [0, 300] 内
-100 <= Node.val <= 100
题目数据保证链表已经按升序 排列
在这里插入图片描述

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
        #
        if head==None or head.next==None:return head
        #
        prev=head
        curr=prev.next
        while curr:
            if curr.val==prev.val:
                prev.next=curr.next
                curr.next=None
                curr=prev.next
            else:
                prev=curr
                curr=prev.next
        return head

lc 82 :删除排序链表中的重复元素 II
https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/
提示:
链表中节点数目在范围 [0, 300] 内
-100 <= Node.val <= 100
题目数据保证链表已经按升序 排列
在这里插入图片描述

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if head==None or head.next==None:return head
        #
        dummynode=ListNode(-1)
        dummynode.next=head
        #
        prev=dummynode
        curr=head
        while curr:
            if curr.next and curr.next.val==curr.val:
                while curr.next and curr.next.val==curr.val:
                    curr=curr.next
                prev.next=curr.next
                curr.next=None
                curr=prev.next
            else:
                prev=curr
                curr=curr.next #curr=prev.next,可以和if里合并
        return dummynode.next

lc 876 :链表的中间结点
https://leetcode.cn/problems/middle-of-the-linked-list/
提示:
给定链表的结点数介于 1 和 100 之间。
在这里插入图片描述在这里插入图片描述

#方案一:两遍扫描
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def middleNode(self, head: ListNode) -> ListNode:
        #链长
        length=0
        curr=head
        while curr:
            length+=1
            curr=curr.next
        #找
        for i in range(length//2):
            head=head.next
        return head
        
#方案二:快慢指针
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def middleNode(self, head: ListNode) -> ListNode:
        if head==None or head.next==None:return head
        slow=fast=head
        while fast and fast.next:#逆否命题
            slow=slow.next
            fast=fast.next.next
        return slow

19 【剑指 021】【top100】 :删除链表的倒数第 N 个结点
https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
提示:
链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
进阶:
你能尝试使用一趟扫描实现吗?
在这里插入图片描述

#方案一:两遍扫描
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        #
        dummynode=ListNode(-1)
        dummynode.next=head
        #链长
        length=0
        curr=dummynode
        while curr:
            length+=1
            curr=curr.next
        #找待删prev
        prev=dummynode
        for i in range(length-n-1):
            prev=prev.next
        #删
        delnode=prev.next
        prev.next=delnode.next
        delnode.next=None
        return dummynode.next

#方案二:快慢指针
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        if not head:return head
        #
        dummynode=ListNode(-1)
        dummynode.next=head
        #fast先走n+1步
        slow=fast=dummynode
        for i in range(n+1):
            fast=fast.next
        # while n >= 0:
        #     fast = fast.next
        #     n -= 1
        while fast:
            slow=slow.next
            fast=fast.next
        #删:此时prev=slow
        delnode=slow.next
        slow.next=delnode.next
        delnode.next=None
        return dummynode.next

lc 141【top100】:环形链表
https://leetcode.cn/problems/linked-list-cycle/
提示:
链表中节点的数目范围是 [0, 104]
-105 <= Node.val <= 105
pos 为 -1 或者链表中的一个 有效索引 。
进阶:
你能用 O(1)(即,常量)内存解决此问题吗?
在这里插入图片描述

#方案一:hash查找
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: Optional[ListNode]) -> bool:
        #o(n),o(n)
        visited=set()
        curr=head
        while curr:
            if curr in visited:return True
            visited.add(curr)
            curr=curr.next
        return False
#方案二:快慢指针
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: Optional[ListNode]) -> bool:
        #o(n),o(1)
        slow=head
        fast=head
        while fast and fast.next:
            slow=slow.next
            fast=fast.next.next
            if slow==fast:return True
        return False

lc 142 【剑指 022 】【top100】:环形链表 II
https://leetcode.cn/problems/linked-list-cycle-ii/
提示:
链表中节点的数目范围在范围 [0, 104] 内
-105 <= Node.val <= 105
pos 的值为 -1 或者链表中的一个有效索引
进阶:
你是否可以使用 O(1) 空间解决此题?
在这里插入图片描述

#方案一:hash查找
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
    	#o(n),o(n)
        visited=set()
        curr=head
        while curr:
            if curr in visited:return curr
            visited.add(curr)
            curr=curr.next
        return None
        
#方案二:快慢指针
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        #o(n).o(1)
        slow=fast=head
        while fast and fast.next:
            slow=slow.next
            fast=fast.next.next
            #有环
            if slow==fast:
                p=head
                while p!=slow:
                    p=p.next
                    slow=slow.next
                return p
        return None

lc 206【剑指 024】【top100】:反转链表
https://leetcode.cn/problems/reverse-linked-list/
提示:
链表中节点的数目范围是 [0, 5000]
-5000 <= Node.val <= 5000
进阶:
链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述

#方案一:迭代
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        prev=None
        curr=head
        while curr:
            nextN=curr.next
            curr.next=prev
            prev=curr
            curr=nextN
        return prev #key
        
#方案二:递归
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        #终条
        if not head or not head.next:return head
        #递
        p=self.reverseList(head.next)#子问题
        #归
        head.next.next=head
        head.next=None
        return p

lc 92 :反转链表 II
https://leetcode.cn/problems/reverse-linked-list-ii/
提示:
链表中节点数目为 n
1 <= n <= 500
-500 <= Node.val <= 500
1 <= left <= right <= n
进阶:
你可以使用一趟扫描完成反转吗?
在这里插入图片描述在这里插入图片描述在这里插入图片描述

#方案一:
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
        #
        dummynode=ListNode(-1)
        dummynode.next=head
        #四个位置
        #
        prev=dummynode
        for i in range(left-1):
            prev=prev.next
        leftN=prev.next
        #
        rightN=leftN
        for i in range(right-left):
            rightN=rightN.next
        post=rightN.next
        #先断
        prev.next=None
        rightN.next=None
        #部分反转
        self.reverseList(leftN)
        #后连
        prev.next=rightN
        leftN.next=post
        return dummynode.next

    def reverseList(self,node):
        prev=None
        curr=node
        while curr:
            nextN=curr.next
            curr.next=prev
            prev=curr
            curr=nextN

#方案二:头插法
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
        #
        dummynode=ListNode(-1)
        dummynode.next=head
        #
        prev=dummynode
        for i in range(left-1):
            prev=prev.next
        curr=prev.next
        #头插
        for i in range(right-left): #头插right-left次
            nextN=curr.next
            curr.next=nextN.next
            nextN.next=prev.next
            prev.next=nextN
        return dummynode.next        

lc 61 :旋转链表
https://leetcode.cn/problems/rotate-list/
提示:
链表中节点的数目在范围 [0, 500] 内
-100 <= Node.val <= 100
0 <= k <= 2 * 10^9
在这里插入图片描述在这里插入图片描述

#方案一:链表反转法
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head or not head.next or k==0:return head    
        #
        length=0
        curr=head
        while curr:
            length+=1
            curr=curr.next
        #改进
        if k%length==0:return head
        k=k%length

        #反1
        newhead1=self.reverseList(head)
        #断
        kthnode=newhead1
        for i in range(k-1):
            kthnode=kthnode.next
        nexthead=kthnode.next
        kthnode.next=None
        #反2,反3,连
        reshead=self.reverseList(newhead1)
        newhead1.next=self.reverseList(nexthead)
        return reshead
        
    def reverseList(self,node):
        prev=None
        curr=node
        while curr:
            nextN=curr.next
            curr.next=prev
            prev=curr
            curr=nextN
        return prev
         
#方案二:处理关键节点
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head or not head.next or k==0:return head    
        ###
        #三个位置
        #lastnode
        length=1
        lastnode=head
        while lastnode.next: #key
            length+=1
            lastnode=lastnode.next
        #lasttail,newhead
        if k%length==0:return head
        k=k%length
        lasttail=head
        for i in range(length-k-1):
            lasttail=lasttail.next
        newhead=lasttail.next
        ###
        #
        lastnode.next=head
        lasttail.next=None
        return newhead    

lc 328 :奇偶链表
https://leetcode.cn/problems/odd-even-linked-list/
提示:
n == 链表中的节点数
0 <= n <= 10^4
-10^6 <= Node.val <= 10^6
你必须在 O(1) 的额外空间复杂度和 O(n) 的时间复杂度下解决这个问题。
在这里插入图片描述

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def oddEvenList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head or not head.next or not head.next.next:return head
        #
        odd,even=head,head.next
        evenhead=head.next
        #
        while even and even.next:
            odd.next=even.next
            odd=odd.next
            even.next=odd.next
            even=even.next
        odd.next=evenhead
        return head

lc 725 :分隔链表
https://leetcode.cn/problems/split-linked-list-in-parts/
提示:
链表中节点的数目在范围 [0, 1000]
0 <= Node.val <= 1000
1 <= k <= 50
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

#方案一:
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def splitListToParts(self, head: Optional[ListNode], k: int) -> List[Optional[ListNode]]:
        #O(n),o(n)
        length=0
        curr=head
        while curr:
            length+=1
            curr=curr.next
        #
        width=length//k
        remain=length%k #remain个长度为width+1的子链表
        #
        res=[ListNode(-1)]*k #key
        curr=head
        for i in range(k):
            dummynode=ListNode(-1)
            node=dummynode
            #
            realwidth=width+(1 if i<=remain-1 else 0)
            for j in range(realwidth):
                node.next=ListNode(curr.val)
                node=node.next
                if curr:curr=curr.next
            res[i]=dummynode.next
        return res
        
#方案二:原链表中分割
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def splitListToParts(self, head: Optional[ListNode], k: int) -> List[Optional[ListNode]]:
        #
        length=0
        curr=head
        while curr:
            length+=1
            curr=curr.next
        #
        width=length//k
        remain=length%k #remain个长度为width+1的子链表
        #
        res=[ListNode(-1)]*k #key
        curr=head
        for i in range(k):
            head=curr #key
            realwidth=width+(1 if i<=remain-1 else 0) 
            #
            for j in range(realwidth-1):#key
                if curr:curr=curr.next
            #注:if curr.next:->output[[1],[2],[3],[3],[3]] real[[1],[2],[3],[],[]]
            if curr:
                nextN=curr.next
                curr.next=None
                curr=nextN
            res[i]=head
        return res   

lc 24 :两两交换链表中的节点
https://leetcode.cn/problems/swap-nodes-in-pairs/
提示:
链表中节点的数目在范围 [0, 100] 内
0 <= Node.val <= 100
在这里插入图片描述
在这里插入图片描述

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head or not head.next:return head
        #
        dummynode=ListNode(-1)
        dummynode.next=head
        #
        prev=dummynode
        first=head
        second=head.next
        while first and second:
            nextN=second.next
            prev.next=second
            second.next=first
            first.next=nextN
            #
            prev=first
            first=nextN
            if not first:break #key
            second=first.next
        return dummynode.next 

lc 25 :K 个一组翻转链表
https://leetcode.cn/problems/reverse-nodes-in-k-group/
提示:
链表中的节点数目为 n
1 <= k <= n <= 5000
0 <= Node.val <= 1000
进阶:
你可以设计一个只用 O(1) 额外内存空间的算法解决此问题吗?
在这里插入图片描述
在这里插入图片描述

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        #
        if not head or not head.next or k<=1:return head
        dummynode=ListNode(-1)
        dummynode.next=head
        #
        prev=dummynode
        first=head
        last=first
        while first:
            #
            for i in range(k-1):
                last=last.next
                if not last:return dummynode.next
            nextN=last.next
            ###反转
            last.next=None
            self.reverseList(first)
            prev.next=last
            first.next=nextN
            ###更新
            prev=first
            first=nextN
            last=first
        return dummynode.next


    def reverseList(self,node):
        prev=None
        curr=node
        while curr:
            nextN=curr.next
            curr.next=prev
            prev=curr
            curr=nextN
        return prev
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值