K 次乘运算后的最终数组状态-LeetCode
3264. K 次乘运算后的最终数组状态 🎯 问题描述 描述: 给你一个整数数组 nums,一个整数 k 和一个整数 multiplier。 你需要对 nums 执行 k 次操作,每次操作中: 找到 nums 中的 最小值 x。如果有多个最小值,选择 下标最小 的那个。 将该最小值替换为 x * multiplier。 请你返回执行完 k 次操作后,最终的 nums 数组。 说明: 这是一个典型的**堆(优先队列)**应用问题。 核心策略: 题目要求每次都要找到“最小”且“下标最小”的元素,这正是最小堆最擅长的操作。 由于 Python 的 heapq 模块默认提供最小堆,我们可以直接将元素存入堆中。 为了满足“数值相同取下标最小”的条件,我们将 (数值, 下标) 作为一个元组存入堆中。Python 在比较元组时,会优先比较第一个元素,如果相同再比较第二个元素,完美契合题目要求。 每次从堆顶取出最小元素,乘以 multiplier 后再放回堆中,重复 k 次即可。 示例: 示例 1: 12345678输入:nums = [2,1,3,5,6], ...
从数量最多的堆取走礼物-LeetCode
2558. 从数量最多的堆取走礼物 🎯 问题描述 描述: 给你一个整数数组 gifts,表示各堆礼物的数量。每一秒,你需要执行以下操作: 选择礼物数量最多的那一堆(如果有多堆数量相同且最多,任选其一)。 将该堆的礼物数量减少到原来的平方根(向下取整)。 返回 k 秒后剩下的礼物总数量。 说明: 这是一个典型的**堆(优先队列)**应用问题。 核心策略: 题目要求每次都要找到当前“最大值”进行操作,这正是最大堆(大根堆)的拿手好戏。 由于 Python 的 heapq 模块默认只提供最小堆,我们依然采用将数值取相反数(负数)的方法,来巧妙地模拟最大堆。 每次从堆顶取出绝对值最大的负数(即最多的礼物堆),计算其平方根后,再将结果的相反数放回堆中。 示例: 示例 1: 12345678输入:gifts = [25,64,9,4,100], k = 4输出:29解释:第1秒:选100,变为 sqrt(100)=10,数组变为 [25,64,9,4,10]第2秒:选64,变为 sqrt(64)=8,数组变为 [25,8,9,4,10]第3秒:选25,变为 ...
执行 K 次操作后的最大分数-LeetCode
执行 K 次操作后的最大分数 🎯 问题描述(来源于LeetCode) 描述: 给你一个下标从 0 开始的整数数组 nums 和一个整数 k。你的起始分数为 0。 在一步操作中: 选出一个满足 0 <= i < nums.length 的下标 i。 将你的分数增加 nums[i]。 将 nums[i] 替换为 ceil(nums[i] / 3)。 返回在恰好执行 k 次操作后,你可能获得的最大分数。 说明: 向上取整函数 ceil(val) 的结果是大于或等于 val 的最小整数。 为了获得最大分数,我们每次都应该贪心地选择当前数组中最大的那个元素。 示例: 示例 1:123输入:nums = [10,10,10,10,10], k = 5输出:50解释:对数组中每个元素执行一次操作。最后分数是 10 + 10 + 10 + 10 + 10 = 50。 示例 2:1234567输入:nums = [1,10,3,3,3], k = 3输出:17解释:第1步:选中10,分数增加10,数组变为 [1, 4, 3, 3, 3]。第2步:选中4,分数增...
按递增顺序显示卡牌-LeetCode
950. 按递增顺序显示卡牌 🎯 问题描述 描述: 牌组中的每张卡牌都对应有一个唯一的整数。你可以按你想要的顺序对这套卡片进行排序。 最初,这些卡牌在牌组里是正面朝下的(即,未显示状态)。 现在,重复执行以下步骤,直到显示所有卡牌为止: 从牌组顶部抽一张牌,显示它,然后将其从牌组中移出。 如果牌组中仍有牌,则将下一张处于牌组顶部的牌放在牌组的底部。 如果仍有未显示的牌,那么返回步骤 1。否则,停止行动。 返回能以递增顺序显示卡牌的牌组顺序。答案中的第一张牌被认为处于牌堆顶部。 说明: 这是一个逆向模拟与队列结合的问题。 核心策略: 我们知道最终显示的顺序必须是从小到大的(即排序后的 deck)。 问题的难点在于:如何安排初始牌序,使得经过“抽一张、移一张到底部”的操作后,刚好能按顺序抽出这些牌? 我们可以模拟抽牌的过程,但不是模拟具体的数字,而是模拟卡牌的位置(下标)。 按照题目规则,第一个被抽出的位置放最小的数,第二个被抽出的位置放第二小的数,以此类推。 示例: 示例 1: 12345678910输入:[17,13,11,2,3,5,7]输出:...
数据流中的第 K 大元素-LeetCode
703.数据流中的第 K 大元素 🎯 问题描述(来源于LeetCode) 描述: 设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,而不是第 k 个不同的元素。 请实现 KthLargest 类: KthLargest(int k, int[] nums):使用整数 k 和整数流 nums 初始化对象。 int add(int val):将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。 说明: 我们不需要保存所有的历史数据,只需要时刻保留当前最大的 k 个元素即可。 这 k 个元素中最小的那个(即堆顶),就是我们要找的第 k 大元素。 示例: 示例 1:1234567891011输入:["KthLargest", "add", "add", "add", "add", "add"][[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]]输出:[nu...
无限集中的最小数字-LeetCode
无限集中的最小数字 🎯 问题描述(来源于LeetCode) 描述: 现有一个包含所有正整数的集合 [1, 2, 3, 4, 5, ...]。请你设计并实现 SmallestInfiniteSet 类。 说明: SmallestInfiniteSet():初始化对象,包含所有正整数。 int popSmallest():移除并返回集合中的最小整数。 void addBack(int num):如果 num 不在集合中,将其添加回集合。 示例: 示例 1:1234输入:["SmallestInfiniteSet", "addBack", "popSmallest", "popSmallest"] [[], [2], [], []]输出:[null, null, 1, 2]解释:初始集合为 [1,2,3,...]。addBack(2) 无效因为2还在。第一次弹出1,第二次弹出2。 示例 2:1234输入:["SmallestInfiniteSet", &...
最后一块石头的重量-LeetCode
1046. 最后一块石头的重量 🎯 问题描述 描述: 有一堆石头,每块石头的重量都是正整数。 每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下: 如果 x == y,那么两块石头都会被完全粉碎; 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。 最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。 说明: 这是一个典型的堆(优先队列)应用问题。 核心策略: 题目要求每次都要取出当前“最大”的两个元素,这正是最大堆(大根堆)最擅长的操作。 由于 Python 的 heapq 模块默认只提供最小堆,我们可以通过将所有石头重量取相反数(负数)存入堆中,从而巧妙地模拟出最大堆的效果。 每次从堆中取出两个最小的负数(即绝对值最大的两个正数)进行碰撞,再将差值的负数放回堆中。 示例: 示例 1: 1234567输入:[2,7,4,1,8,1]输出:1解释:先选出 7 和 8,得到 1,数组变为 [2,...
移除石子使总数最小-LeetCode
1962.移除石子使总数最小 🎯 问题描述(来源于LeetCode) 描述: 给你一个整数数组 piles,其中 piles[i] 表示第 i 堆石子中的石子数量。另给你一个整数 k,请你执行下述操作 恰好 k 次: 选出任一石子堆 piles[i],并从中移除 floor(piles[i] / 2) 颗石子(即向下取整)。 注意:你可以对同一堆石子多次执行此操作。 返回执行 k 次操作后,剩下石子的最小总数。 说明: 为了让剩下的石子总数最小,我们的贪心策略是:每次操作都应该选取当前石子数量最多的一堆来移除。 对最大值进行减半操作,能最大程度地减少石子总数。 示例: 示例 1:123456输入:piles = [5,4,9], k = 2输出:12解释:第1次:对第2堆(9)操作,移除 floor(9/2)=4 颗,变为 [5,4,5]。第2次:对第0堆(5)操作,移除 floor(5/2)=2 颗,变为 [3,4,5]。剩下石子的总数为 3 + 4 + 5 = 12。 示例 2:123输入:piles = [4,3,6,7], k = 3输出:12解释:...
超过阈值的最少操作数II-LeetCode
3066.超过阈值的最少操作数II 🎯 问题描述(来源于LeetCode) 描述: 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。 你可以对 nums 执行一些操作,在一次操作中,你可以: 选择 nums 中 最小 的两个整数 x 和 y 。 将 x 和 y 从 nums 中删除。 将 min(x, y) * 2 + max(x, y) 添加到数组中的任意位置。 注意,只有当 nums 至少包含两个元素时,你才可以执行以上操作。 你需要使数组中的所有元素都 大于或等于 k ,请你返回需要的 最少 操作次数。 说明: 为了用最少的操作次数让所有元素达标,我们的贪心策略是:每次都挑选当前数组中最小的两个数进行合并。这样能最快地把较小的数值“消灭”掉,转化为更大的数值。 示例: 示例 1:123456输入:nums = [2,11,10,1,3], k = 10输出:2解释:第1次操作:选出 1 和 2,合并为 1*2+2=4,数组变为 [3,4,10,11]。第2次操作:选出 3 和 4,合并为 3*2+4=10,数组变为 [10,10,11]。...
最近的请求次数-LeetCode
933. 最近的请求次数 🎯 问题描述 描述: 写一个 RecentCounter 类来计算特定时间范围内最近的请求。 请你实现 RecentCounter 类: RecentCounter() 初始化计数器,请求数为 0。 int ping(int t) 在时间 t 添加一个新请求,其中 t 表示以毫秒为单位的某个时间,并返回过去 3000 毫秒内发生的所有请求数(包括新请求)。确切地说,返回在 [t-3000, t] 内发生的请求数。 说明: 这是一个队列与滑动窗口结合的问题。 核心策略: 每次调用 ping(t) 时,相当于时间窗口的右边界移动到了 t。 我们需要维护队列,使得队列中只保留 [t-3000, t] 范围内的请求时间戳。 利用队列“先进先出”的特性,将超出左边界(小于 t-3000)的旧请求从队首移除。 最终队列的长度就是当前时间窗口内的请求次数。 示例: 示例 1: 123456789101112输入:["RecentCounter", "ping", "ping"...













