2023年9月刷题记录
2023年9月1日
【leetcode】2240. 买钢笔和铅笔的方案数
题意:
给你一个整数
total
,表示你拥有的总钱数。同时给你两个整数cost1
和cost2
,分别表示一支钢笔和一支铅笔的价格。你可以花费你部分或者全部的钱,去买任意数目的两种笔。请你返回购买钢笔和铅笔的 不同方案数目 。
2023年9月2日
【leetcode】2511. 最多可以摧毁的敌人城堡数目
题意:
给你一个长度为
n
,下标从 0 开始的整数数组forts
,表示一些城堡。forts[i]
可以是-1
,0
或者1
,其中:
-1
表示第i
个位置 没有 城堡。0
表示第i
个位置有一个 敌人 的城堡。1
表示第i
个位置有一个你控制的城堡。现在,你需要决定,将你的军队从某个你控制的城堡位置
i
移动到一个空的位置j
,满足:
0 <= i, j <= n - 1
- 军队经过的位置 只有 敌人的城堡。正式的,对于所有
min(i,j) < k < max(i,j)
的k
,都满足forts[k] == 0
。当军队移动时,所有途中经过的敌人城堡都会被 摧毁 。
请你返回 最多 可以摧毁的敌人城堡数目。如果 无法 移动你的军队,或者没有你控制的城堡,请返回
0
。
2023年9月3日
【leetcode】1921. 消灭怪物的最大数量
题意:
你正在玩一款电子游戏,在游戏中你需要保护城市免受怪物侵袭。给你一个 下标从 0 开始 且长度为
n
的整数数组dist
,其中dist[i]
是第i
个怪物与城市的 初始距离(单位:米)。怪物以 恒定 的速度走向城市。给你一个长度为
n
的整数数组speed
表示每个怪物的速度,其中speed[i]
是第i
个怪物的速度(单位:米/分)。怪物从 第 0 分钟 时开始移动。你有一把武器,并可以 选择 在每一分钟的开始时使用,包括第 0 分钟。但是你无法在一分钟的中间使用武器。这种武器威力惊人,一次可以消灭任一还活着的怪物。
一旦任一怪物到达城市,你就输掉了这场游戏。如果某个怪物 恰 在某一分钟开始时到达城市,这会被视为 输掉 游戏,在你可以使用武器之前,游戏就会结束。
返回在你输掉游戏前可以消灭的怪物的 最大 数量。如果你可以在所有怪物到达城市前将它们全部消灭,返回
n
。
2023年9月4日
【leetcode】449. 序列化和反序列化二叉搜索树
题意:
序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。
设计一个算法来序列化和反序列化 二叉搜索树 。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。
编码的字符串应尽可能紧凑。
2023年9月5日
【leetcode】2605. 从两个数字数组里生成最小数字
题意:
给你两个只包含 1 到 9 之间数字的数组
nums1
和nums2
,每个数组中的元素 互不相同 ,请你返回 最小 的数字,两个数组都 至少 包含这个数字的某个数位。
2023年9月6日
【leetcode】1123. 最深叶节点的最近公共祖先
题意:
给你一个有根节点
root
的二叉树,返回它 最深的叶节点的最近公共祖先 。回想一下:
- 叶节点 是二叉树中没有子节点的节点
- 树的根节点的 深度 为
0
,如果某一节点的深度为d
,那它的子节点的深度就是d+1
- 如果我们假定
A
是一组节点S
的 最近公共祖先,S
中的每个节点都在以A
为根节点的子树中,且A
的深度达到此条件下可能的最大值。
2023年9月7日
【leetcode】2594. 修车的最少时间
题意:
给你一个整数数组
ranks
,表示一些机械工的 能力值 。ranks_i
是第i
位机械工的能力值。能力值为r
的机械工可以在r * n ^ 2
分钟内修好n
辆车。同时给你一个整数
cars
,表示总共需要修理的汽车数目。请你返回修理所有汽车 最少 需要多少时间。
注意:所有机械工可以同时修理汽车。
2023年9月8日
【leetcode】2651. 计算列车到站时间
题意:
给你一个正整数
arrivalTime
表示列车正点到站的时间(单位:小时),另给你一个正整数delayedTime
表示列车延误的小时数。返回列车实际到站的时间。
注意,该问题中的时间采用 24 小时制。
2023年9月9日
【leetcode】207. 课程表
题意:
你这个学期必须选修
numCourses
门课程,记为0
到numCourses - 1
。在选修某些课程之前需要一些先修课程。 先修课程按数组
prerequisites
给出,其中prerequisites[i] = [ai, bi]
,表示如果要学习课程ai
则 必须 先学习课程bi
。
- 例如,先修课程对
[0, 1]
表示:想要学习课程0
,你需要先完成课程1
。请你判断是否可能完成所有课程的学习?如果可以,返回
true
;否则,返回false
。
2023年9月10日
【leetcode】210. 课程表 II
题意:
现在你总共有
numCourses
门课需要选,记为0
到numCourses - 1
。给你一个数组prerequisites
,其中prerequisites[i] = [ai, bi]
,表示在选修课程ai
前 必须 先选修bi
。
- 例如,想要学习课程
0
,你需要先完成课程1
,我们用一个匹配来表示:[0,1]
。返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组 。
2023年9月11日
【leetcode】630. 课程表 III
题意:
这里有
n
门不同的在线课程,按从1
到n
编号。给你一个数组courses
,其中courses[i] = [durationi, lastDayi]
表示第i
门课将会 持续 上durationi
天课,并且必须在不晚于lastDayi
的时候完成。你的学期从第
1
天开始。且不能同时修读两门及两门以上的课程。返回你最多可以修读的课程数目。
2023年9月12日
【leetcode】1462. 课程表 IV
题意:
你总共需要上
numCourses
门课,课程编号依次为0
到numCourses-1
。你会得到一个数组prerequisite
,其中prerequisites[i] = [ai, bi]
表示如果你想选bi
课程,你 必须 先选ai
课程。
- 有的课会有直接的先修课程,比如如果想上课程
1
,你必须先上课程0
,那么会以[0,1]
数对的形式给出先修课程数对。先决条件也可以是 间接 的。如果课程
a
是课程b
的先决条件,课程b
是课程c
的先决条件,那么课程a
就是课程c
的先决条件。你也得到一个数组
queries
,其中queries[j] = [uj, vj]
。对于第j
个查询,您应该回答课程uj
是否是课程vj
的先决条件。返回一个布尔数组
answer
,其中answer[j]
是第j
个查询的答案。
2023年9月13日
【leetcode】2596. 检查骑士巡视方案
题意:
骑士在一张
n x n
的棋盘上巡视。在 有效 的巡视方案中,骑士会从棋盘的 左上角 出发,并且访问棋盘上的每个格子 恰好一次 。给你一个
n x n
的整数矩阵grid
,由范围[0, n * n - 1]
内的不同整数组成,其中grid[row][col]
表示单元格(row, col)
是骑士访问的第grid[row][col]
个单元格。骑士的行动是从下标 0 开始的。如果
grid
表示了骑士的有效巡视方案,返回true
;否则返回false
。注意,骑士行动时可以垂直移动两个格子且水平移动一个格子,或水平移动两个格子且垂直移动一个格子。下图展示了骑士从某个格子出发可能的八种行动路线。
2023年9月14日
【leetcode】1222. 可以攻击国王的皇后
题意:
在一个 8x8 的棋盘上,放置着若干「黑皇后」和一个「白国王」。
给定一个由整数坐标组成的数组
queens
,表示黑皇后的位置;以及一对坐标king
,表示白国王的位置,返回所有可以攻击国王的皇后的坐标(任意顺序)。
2023年9月15日
【leetcode】LCP 50. 宝石补给
题意:
欢迎各位勇者来到力扣新手村,在开始试炼之前,请各位勇者先进行「宝石补给」。
每位勇者初始都拥有一些能量宝石,
gem[i]
表示第i
位勇者的宝石数量。现在这些勇者们进行了一系列的赠送,operations[j] = [x, y]
表示在第j
次的赠送中 第x
位勇者将自己一半的宝石(需向下取整)赠送给第y
位勇者。在完成所有的赠送后,请找到拥有最多宝石的勇者和拥有最少宝石的勇者,并返回他们二者的宝石数量之差。
注意:
- 赠送将按顺序逐步进行。
2023年9月16日
【leetcode】198. 打家劫舍
题意:
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
2023年9月17日
【leetcode】213. 打家劫舍 II
题意:
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
2023年9月18日
【leetcode】337. 打家劫舍 III
题意:
小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为
root
。除了
root
之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。给定二叉树的
root
。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
2023年9月19日
【leetcode】2560. 打家劫舍 IV
题意:
沿街有一排连续的房屋。每间房屋内都藏有一定的现金。现在有一位小偷计划从这些房屋中窃取现金。
由于相邻的房屋装有相互连通的防盗系统,所以小偷 不会窃取相邻的房屋 。
小偷的 窃取能力 定义为他在窃取过程中能从单间房屋中窃取的 最大金额 。
给你一个整数数组
nums
表示每间房屋存放的现金金额。形式上,从左起第i
间房屋中放有nums[i]
美元。另给你一个整数
k
,表示窃贼将会窃取的 最少 房屋数。小偷总能窃取至少k
间房屋。返回小偷的 最小 窃取能力。
2023年9月20日
【leetcode】LCP 06. 拿硬币
题意:
桌上有
n
堆力扣币,每堆的数量保存在数组coins
中。我们每次可以选择任意一堆,拿走其中的一枚或者两枚,求拿完所有力扣币的最少次数。
2023年9月21日
【leetcode】2439. 最小化数组中的最大值
题意:
给你一个下标从 0 开始的数组
nums
,它含有n
个非负整数。每一步操作中,你需要:
- 选择一个满足
1 <= i < n
的整数i
,且nums[i] > 0
。- 将
nums[i]
减 1 。- 将
nums[i - 1]
加 1 。你可以对数组执行 任意 次上述操作,请你返回可以得到的
nums
数组中 最大值 最小 为多少。
2023年9月22日
【leetcode】2591. 将钱分给最多的儿童
题意:
给你一个整数
money
,表示你总共有的钱数(单位为美元)和另一个整数children
,表示你要将钱分配给多少个儿童。你需要按照如下规则分配:
- 所有的钱都必须被分配。
- 每个儿童至少获得
1
美元。- 没有人获得
4
美元。请你按照上述规则分配金钱,并返回 最多 有多少个儿童获得 恰好
8
美元。如果没有任何分配方案,返回-1
。
2023年9月23日
【leetcode】1993. 树上的操作
题意:
给你一棵
n
个节点的树,编号从0
到n - 1
,以父节点数组parent
的形式给出,其中parent[i]
是第i
个节点的父节点。树的根节点为0
号节点,所以parent[0] = -1
,因为它没有父节点。你想要设计一个数据结构实现树里面对节点的加锁,解锁和升级操作。数据结构需要支持如下函数:
- Lock:指定用户给指定节点 上锁 ,上锁后其他用户将无法给同一节点上锁。只有当节点处于未上锁的状态下,才能进行上锁操作。
- Unlock:指定用户给指定节点 解锁 ,只有当指定节点当前正被指定用户锁住时,才能执行该解锁操作。
- Upgrade:指定用户给指定节点 上锁 ,并且将该节点的所有子孙节点 解锁 。只有如下 3 个条件 全部 满足时才能执行升级操作:
- 指定节点当前状态为未上锁。
- 指定节点至少有一个上锁状态的子孙节点(可以是 任意 用户上锁的)。
- 指定节点没有任何上锁的祖先节点。
请你实现
LockingTree
类:
LockingTree(int[] parent)
用父节点数组初始化数据结构。lock(int num, int user)
如果 id 为user
的用户可以给节点num
上锁,那么返回true
,否则返回false
。如果可以执行此操作,节点num
会被 id 为user
的用户 上锁 。unlock(int num, int user)
如果 id 为user
的用户可以给节点num
解锁,那么返回true
,否则返回false
。如果可以执行此操作,节点num
变为 未上锁 状态。upgrade(int num, int user)
如果 id 为user
的用户可以给节点num
升级,那么返回true
,否则返回false
。如果可以执行此操作,节点num
会被 升级 。
2023年9月24日
【leetcode】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)
的平均时间复杂度运行。
2023年9月25日
【leetcode】460. LFU 缓存
题意:
请你为 最不经常使用(LFU)缓存算法设计并实现数据结构。
实现
LFUCache
类:
LFUCache(int capacity)
- 用数据结构的容量capacity
初始化对象int get(int key)
- 如果键key
存在于缓存中,则获取键的值,否则返回-1
。void put(int key, int value)
- 如果键key
已存在,则变更其值;如果键不存在,请插入键值对。当缓存达到其容量capacity
时,则应该在插入新项之前,移除最不经常使用的项。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 最久未使用 的键。为了确定最不常使用的键,可以为缓存中的每个键维护一个 使用计数器 。使用计数最小的键是最久未使用的键。
当一个键首次插入到缓存中时,它的使用计数器被设置为
1
(由于 put 操作)。对缓存中的键执行get
或put
操作,使用计数器的值将会递增。函数
get
和put
必须以O(1)
的平均时间复杂度运行。
2023年9月26日
【leetcode】2582. 递枕头
题意:
n
个人站成一排,按从1
到n
编号。最初,排在队首的第一个人拿着一个枕头。每秒钟,拿着枕头的人会将枕头传递给队伍中的下一个人。一旦枕头到达队首或队尾,传递方向就会改变,队伍会继续沿相反方向传递枕头。
- 例如,当枕头到达第
n
个人时,TA 会将枕头传递给第n - 1
个人,然后传递给第n - 2
个人,依此类推。给你两个正整数
n
和time
,返回time
秒后拿着枕头的人的编号。
2023年9月27日
【leetcode】1333. 餐厅过滤器
题意:
给你一个餐馆信息数组
restaurants
,其中restaurants[i] = [idi, ratingi, veganFriendlyi, pricei, distancei]
。你必须使用以下三个过滤器来过滤这些餐馆信息。其中素食者友好过滤器
veganFriendly
的值可以为true
或者false
,如果为 true 就意味着你应该只包括veganFriendlyi
为 true 的餐馆,为 false 则意味着可以包括任何餐馆。此外,我们还有最大价格maxPrice
和最大距离maxDistance
两个过滤器,它们分别考虑餐厅的价格因素和距离因素的最大值。过滤后返回餐馆的 *id*,按照 rating 从高到低排序。如果 rating 相同,那么按 id 从高到低排序。简单起见,
veganFriendlyi
和veganFriendly
为 true 时取值为 1,为 false 时,取值为 0 。
2023年9月28日
【leetcode】2251. 花期内花的数目
题意:
给你一个下标从 0 开始的二维整数数组
flowers
,其中flowers[i] = [starti, endi]
表示第i
朵花的 花期 从starti
到endi
(都 包含)。同时给你一个下标从 0 开始大小为n
的整数数组people
,people[i]
是第i
个人来看花的时间。请你返回一个大小为
n
的整数数组answer
,其中answer[i]
是第i
个人到达时在花期内花的 数目 。
2023年9月29日
【leetcode】605. 种花问题
题意:
假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给你一个整数数组
flowerbed
表示花坛,由若干0
和1
组成,其中0
表示没种植花,1
表示种植了花。另有一个数n
,能否在不打破种植规则的情况下种入n
朵花?能则返回true
,不能则返回false
。
2023年9月30日
【leetcode】2136. 全部开花的最早一天
题意:
你有
n
枚花的种子。每枚种子必须先种下,才能开始生长、开花。播种需要时间,种子的生长也是如此。给你两个下标从 0 开始的整数数组plantTime
和growTime
,每个数组的长度都是n
:
plantTime[i]
是 播种 第i
枚种子所需的 完整天数 。每天,你只能为播种某一枚种子而劳作。无须 连续几天都在种同一枚种子,但是种子播种必须在你工作的天数达到plantTime[i]
之后才算完成。growTime[i]
是第i
枚种子完全种下后生长所需的 完整天数 。在它生长的最后一天 之后 ,将会开花并且永远 绽放 。从第
0
开始,你可以按 任意 顺序播种种子。返回所有种子都开花的 最早 一天是第几天。