力扣(python3)2026.4.3自用
138.随机链表的复制
给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。
构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。
返回复制链表的头节点。
用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
val:一个表示Node.val的整数。random_index:随机指针指向的节点索引(范围从0到n-1);如果不指向任何节点,则为null。
你的代码 只 接受原链表的头节点 head 作为传入参数。
思路: 今天做的题都没有什么思路,可能第一次见,有思路也不对。进展有点慢
这个题,如果没有random这个指针的话,只有next,那只需要边构建节点,边复制val 然后连接到新的链表上就可以了。但是有random的话,它的指向是随机的,它指向的节点,可能目前构造不出来。
正解:将原链表的节点和新链表的节点,用哈希表,做一个映射。这样 .next和 random都可以通过这个哈希表来完成。需要注意dct.get()这个函数,意思是没有这个key 就会返回None
"""
# Definition for a Node.
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = int(x)
self.next = next
self.random = random
"""
class Solution:
def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
if head == None:
return None
# 旧节点和新节点做映射,构造哈希,保证新节点的指针指向的都是新节点
cur = head
dct = {}
while cur:
dct[cur] = Node(cur.val)
cur = cur.next
# 怎么把新节点都连接起来
cur = head
while cur:
dct[cur].next = dct.get(cur.next)
dct[cur].random = dct.get(cur.random)
cur = cur.next
return dct[head]
148.排序链表
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
示例 1:

输入:head = [4,2,1,3] 输出:[1,2,3,4]
思路:这个题要求时间复杂度为O(NlogN) 。关于排序问题,时间复杂度小的就是 归并排序,快排和堆排。这个题用归并排序。那就需要把链表从中间断开处理,然后不断递归。递归的过程是不断断开的过程,最后需要一次总的合并。从中间断开,需要快慢指针。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
# 时间复杂度很低的话,排序有归并,快排和堆排
# 这个题用归并,先利用快慢指针,把链表分成2份,然后每份自己排,这个就是递归的过程。最后利用合并两个有序链表,合并起来
if not head or head.next == None:
return head
slow = head
fast = head.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
mid = slow.next
slow.next = None
left = self.sortList(head) #因为slow指针已经把链表分开了
right = self.sortList(mid)
return self.mergeList(left,right)
def mergeList(self,left:ListNode,right:ListNode):
dummy = ListNode(-1)
tmp = dummy
l = left
r = right
while l and r:
if l.val < r.val:
tmp.next = l
l = l.next
else:
tmp.next = r
r = r.next
tmp = tmp.next
tmp.next = l if l else r
return dummy.next
23.合并K个升序链表
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]] 输出:[1,1,2,3,4,4,5,6] 解释:链表数组如下: [ 1->4->5, 1->3->4, 2->6 ] 将它们合并到一个有序链表中得到。 1->1->2->3->4->4->5->6
思路:这个题和上面题类似。分治思想,两两合并,得到一个升序链表,然后再两两合并,最后合并为一个升序链表。需要一个递归函数不断处理从中间断开的过程,然后最后进行一次合并
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
# 合并所有的,总合并
if not lists:
return None
l = 0
r = len(lists) - 1
return self.merge(lists,l,r)
def merge(self,lists,l,r):
if l == r:
return lists[l]
mid = (l + r) //2
left = self.merge(lists,l,mid)
right = self.merge(lists,mid + 1,r)
return self.mergeTwolists(left,right)
def mergeTwolists(self,left,right):
dummy = ListNode(-1)
cur = dummy
while left and right:
if left.val < right.val:
cur.next = left
left = left.next
else:
cur.next = right
right = right.next
cur = cur.next
cur.next = left if left else right
return dummy.next
146.LRU缓存
请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity)以 正整数 作为容量capacity初始化 LRU 缓存int get(int key)如果关键字key存在于缓存中,则返回关键字的值,否则返回-1。void put(int key, int value)如果关键字key已经存在,则变更其数据值value;如果不存在,则向缓存中插入该组key-value。如果插入操作导致关键字数量超过capacity,则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。
示例:
输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]
解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4
思路:这个题看到之后没想法,看答案,是哈希表 + 双向链表。
正解: 哈希表用来存储 key和节点的映射,方便快速查找是否存在这个节点;双向链表用来快速的删除和添加节点。
需要定义head 和tail 节点,head之后的节点为最新使用的,tail之前的节点为最久不使用的。
# 哈希表 + 双向链表,哈希表映射key和节点,这样可以快速判断存不存在;
# 双向链表可以快速删除和增加节点
# 1、定义双向链表
# 2、定义head和tail节点,head之后的节点为最新操作过的,tail前节点为最久不使用的
class DlinkListNode:
def __init__(self,key = 0,value = 0):
self.key = key
self.value = value
self.next = None
self.prev = None
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.head = DlinkListNode()
self.tail = DlinkListNode()
self.head.next = self.tail
self.tail.prev = self.head
self.mp = {} # key和节点的映射
def move(self,node):
node.next = self.head.next
self.head.next.prev = node
self.head.next = node
node.prev = self.head
def dele(self,node):
node.prev.next = node.next
node.next.prev = node.prev
def get(self, key: int) -> int:
# 判断当前在不在哈希表,在返回value并移到head后面,还需要再当前位置删除节点。不在返回-1
# 定义移动到head后面的函数,方便复用
if key in self.mp:
self.dele(self.mp[key])
self.move(self.mp[key])
return self.mp[key].value
return -1
def put(self, key: int, value: int) -> None:
# 判断当前是否存在
if key in self.mp:
self.mp[key].value = value
self.dele(self.mp[key])
self.move(self.mp[key])
else:
node = DlinkListNode(key,value)
self.move(node)
self.mp[key] = node
if len(self.mp) > self.capacity:
tail_prev = self.tail.prev
self.dele(tail_prev)
del self.mp[tail_prev.key]
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)