数据规模->时间复杂度
<=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