【LeetCode周赛】2022上半年题目精选集——贪心

news/2024/11/23 12:56:13/

文章目录

  • 2136. 全部开花的最早一天(贪心)⭐⭐⭐⭐⭐
      • 思路
      • 代码
        • 语法解析:Integer[] id = IntStream.range(0, plantTime.length).boxed().toArray(Integer[]::new);
  • 2141. 同时运行 N 台电脑的最长时间(贪心)⭐⭐⭐⭐⭐
    • 解法1——二分答案
    • 解法2——排序+贪心
      • 思路
      • 代码
  • 2234. 花园的最大总美丽值(贪心)
  • 2311. 小于等于 K 的最长二进制子序列(贪心)
    • 解法1——双指针删去最前面的1
    • 解法2——分类讨论+贪心
      • 补充:public static int numberOfLeadingZeros​(int i)
      • 补充:public static int parseInt​(String s, int radix) throws NumberFormatException

2136. 全部开花的最早一天(贪心)⭐⭐⭐⭐⭐

2136. 全部开花的最早一天
难度:2033
在这里插入图片描述

思路

贪心省流版:
花期越长的,越早种植。

完整版:
参见
https://leetcode.cn/problems/earliest-possible-day-of-full-bloom/solutions/1202113/quan-bu-kai-hua-de-zui-zao-yi-tian-by-le-ocxg/
https://leetcode.cn/problems/earliest-possible-day-of-full-bloom/solutions/1200254/tan-xin-ji-qi-zheng-ming-by-endlesscheng-hfwe/

代码

class Solution {public int earliestFullBloom(int[] plantTime, int[] growTime) {Integer[] id = IntStream.range(0, plantTime.length).boxed().toArray(Integer[]::new);Arrays.sort(id, (i, j) -> growTime[j] - growTime[i]);   // 按照开花时间降序排序int ans = 0, day = 0;for (int i : id) {day += plantTime[i];ans = Math.max(ans, day + growTime[i]);}return ans;}
}

语法解析:Integer[] id = IntStream.range(0, plantTime.length).boxed().toArray(Integer[]::new);

生成0~plantTime.length - 1的 int 流,然后装箱即转成Integer,最后使用 toArray() 转成数组类型。

注意:这里 toArray() 中必须使用 Integer[]::new,因为这是 Stream 类的 toArray() 方法,
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html#toArray(java.util.function.IntFunction),它返回一个包含此流元素的数组,使用提供的生成器函数来分配返回的数组,以及分区执行或调整大小所需的任何其他数组。
在这里插入图片描述

ArrayList 的 toArray 操作如下:
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ArrayList.html#toArray(T[])
在这里插入图片描述

2141. 同时运行 N 台电脑的最长时间(贪心)⭐⭐⭐⭐⭐

2141. 同时运行 N 台电脑的最长时间

难度:2265

在这里插入图片描述
提示:

1 <= n <= batteries.length <= 10^5
1 <= batteries[i] <= 10^9

解法1——二分答案

在这里插入图片描述
二分是 log ,判断合不合理是 n。
其中判断是否合理的方法基于:电量 > x 的只能被使用 x ,小于 x 的可以充分使用,最后计算这些可用电量之和能否支持 n 个机器运行 x 时长。

class Solution {public long maxRunTime(int n, int[] batteries) {long l = 0, r = (long)1e15;while (l < r) {long mid = l + r + 1 >> 1;if (op(n, batteries, mid)) l = mid;else r = mid - 1;}return l;}public boolean op(int n, int[] batteries, long k) {long sum = 0;for (int battery: batteries) sum += Math.min(battery, k);return n <= sum / k;	// 这里不能写成 n * k <= sum; 否则会产生溢出问题}
}

解法2——排序+贪心

思路

在这里插入图片描述

代码

核心思想就是:先把大的不能充分利用的都给删掉,剩下的小的都可以充分使用所以直接返回 sum / n。

class Solution {public long maxRunTime(int n, int[] batteries) {long sum = 0;for (int battery: batteries) sum += battery;Arrays.sort(batteries);for (int i = batteries.length - 1; i >= 0; --i) {int battery = batteries[i];if (battery <= sum / n) {return sum / n;     // 剩下的电池都比较小,都可以充分使用} else {// 消耗掉这个电池sum -= battery;n--;}}return 0;}
}

2234. 花园的最大总美丽值(贪心)

2234. 花园的最大总美丽值
难度:2561

在这里插入图片描述
在这里插入图片描述


思路是先假设所有花园都可以补到 target ,这时候计算还剩多少个可以用的花朵。

然后从前往后枚举不能补到 target 的前缀,将可以用的花朵逐渐增加,在这个过程中计算不完善花园的最小值最大可以是多少 (leftFlowers + sumFlowers)/ x。

并且在这个枚举过程中不断通过 Math.max() 更新答案。

class Solution {public long maximumBeauty(int[] flowers, long newFlowers, int target, int full, int partial) {long n = flowers.length;Arrays.sort(flowers);  // 升序排序if (flowers[0] >= target) return n * full;// 填充后缀后剩余可以使用的花朵long leftFlowers = newFlowers - target * n; for (int i = 0; i < n; ++i) {flowers[i] = Math.min(flowers[i], target);  // 计算多余的花leftFlowers += flowers[i];}long ans = 0L, sumFlowers = 0L;for (int i = 0, x = 0; i <= n; ++i) {           // 枚举后缀长度 n - iif (leftFlowers >= 0) {                     // 有剩余的花,说明后缀全是full// 计算最长前缀的长度。// 剩余的花够补到flowers[x]while (x < i && (long)flowers[x] * x - sumFlowers <= leftFlowers) { // 计算前缀已有花的总数sumFlowers += flowers[x++];         }long beauty = (n - i) * full;// x > 0 说明有前缀,需要确保不会前缀的各个取值不会大于targetif (x > 0) beauty += Math.min((leftFlowers + sumFlowers) / x, (long)target - 1) * partial;      ans = Math.max(ans, beauty);            // 更新答案}// i不需要补到target,剩余的花数量增加if (i < n) leftFlowers += target - flowers[i];  }return ans;}
}

2311. 小于等于 K 的最长二进制子序列(贪心)

2311. 小于等于 K 的最长二进制子序列

难度:1839

在这里插入图片描述

注意是最长子序列 而不是 最长连续子序列。

解法1——双指针删去最前面的1

前导零不会影响二进制数字的大小,当数字过大时,不断删去最开头的1知道数字满足条件即可。

class Solution {public int longestSubsequence(String s, int k) {int n = s.length(), sum = 0, ans = 0, t = 0;List<Integer> nums = new LinkedList();  // 记录1出现的位置for (int i = 0; i < n; ++i) {++t;sum = sum * 2;if (s.charAt(i) == '1') {sum++;nums.add(i);}while (sum > k) {                   // 删去最靠前的1sum -= 1 << (i - nums.get(0));nums.remove(0);--t;}ans = Math.max(ans, t);}return ans;}
}

解法2——分类讨论+贪心

在这里插入图片描述

直接看代码中的注释就可以理解思路了。

class Solution {public int longestSubsequence(String s, int k) {// m是k的2进制中从第一个1到最右边的位数int n = s.length(), m = 32 - Integer.numberOfLeadingZeros(k);// 如果n<m,那么s全选也会<=kif (n < m) return n;// 按2进制解析s.substring(n - m)的数值,<=k就可以全选这部分,否则需要删除1位var ans = Integer.parseInt(s.substring(n - m), 2) <= k ? m : m - 1;// 给结果加上前面的所有0的数量return ans + (int) s.substring(0, n - m).chars().filter(c -> c == '0').count();}
}

补充:public static int numberOfLeadingZeros​(int i)

在这里插入图片描述

返回指定int值的二进制补码表示中最高阶(“最左边”)一位之前的零位数。如果指定的值在其二进制补码表示中没有一位,即等于零,则返回32。

与之相对的还有:public static int numberOfTrailingZeros​(int i)
在这里插入图片描述
返回指定int值的二进制补码表示形式中的最低阶(“最右边”)一位之后的零位数。如果指定的值在其二进制的补码表示中没有一位,即等于零,则返回32。

补充:public static int parseInt​(String s, int radix) throws NumberFormatException

public static int parseInt​(String s, int radix) throws NumberFormatException
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Integer.html#parseInt(java.lang.String,int)
在这里插入图片描述

将字符串参数解析为第二个参数指定基数的带符号整数。


http://www.ppmy.cn/news/769856.html

相关文章

Shamir秘密共享

目录 Shamir秘密共享 秘密共享的概念 问题1: 问题2: 秘密分割门限方案的定义 Shamir秘密共享方案 组成 构造思路 构造 计算f(x) 例1 例2 二、GMW方案 Shamir秘密共享 秘密共享的概念 问题1: 保险柜中存放有10个人的共有财产&#xff0c;要从保险柜中取出物品&am…

509实验室打印机双面打印的方法

1.首先IP地址为&#xff1a;10.20.105.145 方法1&#xff1a; 1.用wps有个双面打印&#xff0c;然后打印完需要把打印完单面的纸给纵向翻转&#xff0c;让有字体的那一面朝上&#xff0c;并且字的朝向为右&#xff0c;最后一步就是把这些纸的最上面的挪到最下面&#xff0c;依…

想请问下PDF双面打印时(打印机自动双面打印)为什么反面那页的内容是倒过来的,应该怎么设置?...

用foxit reader 打印pdf 直接设置为双面打印并且一张2页打印&#xff0c;发现正反面刚好倒着来的&#xff0c;其实说的正反面倒着是从左右翻的角度来讲的&#xff0c;如果上下翻会发现刚好是这个顺序的&#xff0c;这个是要在双面打印设置里头去设置那个长边和短边的方向。在fo…

为什么使用Adobe Acrobat打开pdf,不能双面打印,而 word 却可以双面打印

为什么会出现这样的事情呢&#xff1f; 经查阅资料发现原来是本地默认的打印机没有安装 双面打印的组件 。 解决方法如下&#xff1a; 安装 双面打印组件 1、选择 开始——> 设备和打印机——> 找到默认的打印机 2、右键 打印机属性 3、找到 配置——> 点击 可安装选项…

WPSOffice双面文档打印边距设置(转)

WPSOffice双面文档打印边距设置(转) 通常我们在打印文档时&#xff0c;多数情况下都会把文档左侧的页边距设置的大一些&#xff0c;这样有利于我们进行装订。但是当进行双面打印时&#xff0c;左右页边距在纸张的两面正好相反&#xff0c;反而难于装订了。在WPS Office中我们可…

书籍折页是什么效果_问题:WPS里页面设置中的拼页,书籍折页,反向书籍折页分别是什么意思?打印出来的效果是什么样的? 要双面打印...

问题&#xff1a;WPS里页面设置中的拼页&#xff0c;书籍折页&#xff0c;反向书籍折页分别是什么意思&#xff1f;打印出来的效果是什么样的&#xff1f; 要双面打印 发表日期&#xff1a;2016-03-29 23:10:02 浏览:1121 分享给朋友&#xff1a; 导语专业顾问回答&#xff1a;…

WPS表格奇偶数页打印怎么设置?如何只打印奇数页?

平时我们在打印 WPS 文字的时候&#xff0c;可以很轻松地选择打印奇偶页或只打印奇数页或偶数页&#xff0c;详见『WPS 如何设置打印奇数页和偶数页&#xff1f;』。但是如果我们需要打印 WPS 表格里面的内容就无法找到“打印”也无法选择“奇数页”或“偶数页”&#xff0c;这…

Word2010文档在纸张背面打印以进行双面打印

当使用支持双面打印的打印机打印Word2010文档时&#xff0c;用户可以通过设置在纸张背面打印当前Word文档&#xff0c;以实现双面打印的目的&#xff0c;操作步骤如下所述&#xff1a; 1.打开Word2010文档窗口&#xff0c;依次单击“文件”→“选项”命令&#xff0c;如图20111…