做Java的,堪比清末进宫的太监。。。
最近刷到一个帖子,有网友吐槽:“做Java的,堪比清末进宫的太监。”我直接笑喷了,网友的比喻是越来越离谱了。😂
不过说实话,程序员的日子确实不轻松。有人觉得Java内卷得像高考一样,竞争惨烈;结果评论区一水儿的“别的语言好过?前端、Go、Python哪个轻松?”好家伙,这不光Java,整个编程行业都在“卷”里沦陷。
我觉得这不是某个语言的问题,而是整个行业的大趋势。要说图个轻松,那可能得去养猪了(别问,问就是有AI养猪了)。🐷
不过,编程行业虽然“卷”,但也有它的魅力。所以,大家既然选了这条路,就咬咬牙坚持下去吧,天亮后会有更多需求等着你(手动狗头)。
你们觉得做哪门语言最轻松?欢迎在评论区聊聊~(备注:文末可领最新资料)。
算法题:设置交集大小至少为2
最近刷到一道算法题,挺有意思,和大家唠唠。
题目大致是这样的:给你一组区间,让你找到一个集合,这个集合里的元素要覆盖每个区间,且每个区间里至少有两个数字,问你集合的最小大小是多少。
一看这题,我心里咯噔一下——这不是标准的区间贪心问题嘛!🤔想想日常工作里,不管是排任务调度,还是接口吞吐分析,贪心算法总能让人头皮发麻,但也特别香,因为效率是真高。
先看问题:区间交集大小至少为 2,说白了就是要在每个区间里选两个数,选得少还得让所有区间满意。怎么搞?贪心上场!
基本思路:
把这些区间按照右端点从小到大排序。 然后优先从右端点挑数字(因为右端点靠后,往前覆盖的可能性更高)。 每选一个区间时,尽量在右端点往回数两个位置。
下面直接上代码,说清楚点:
import java.util.*;public class IntersectionSize {
public int intersectionSizeTwo(int[][] intervals) {
// 按右端点升序,右端点相同时按左端点降序
Arrays.sort(intervals, (a, b) -> a[1] == b[1] ? b[0] - a[0] : a[1] - b[1]);
int res = 0;
int first = -1, second = -1; // 记录最后选的两个点
for (int[] interval : intervals) {
int start = interval[0], end = interval[1];
// 检查当前区间是否已被覆盖
boolean needFirst = (first < start); // 第一个点是否需要更新
boolean needSecond = (second < start); // 第二个点是否需要更新
if (needFirst) {
// 如果第一个点都不够,说明需要更新两个点
res += 2;
second = end;
first = end - 1;
} else if (needSecond) {
// 如果只有第二个点不够,更新一个点
res += 1;
first = second;
second = end;
}
}
return res;
}
public static void main(String[] args) {
IntersectionSize solver = new IntersectionSize();
int[][] intervals = {{1, 3}, {3, 7}, {5, 6}, {6, 9}};
System.out.println("Minimum set size: " + solver.intersectionSizeTwo(intervals));
}
}
代码说完了,来聊聊为啥这样干。
排序的时候,我们按右端点升序、左端点降序排,是为了尽可能少地扩展区间。想象一下,如果先处理右端点更大的区间,会导致前面的区间覆盖得乱七八糟,还得额外增加集合里的数字。这就像写代码里的“递归先从最小问题开始处理”,越精简越好。
贪心选点时,first 和 second 是我们维护的两个“最小必要点”。如果某个区间 start 到 end,连 first 都小于 start,说明之前选的点全用不上了,那只能硬加两个点。这种情况就像线上紧急修复 bug,必须得加班上手,没得商量。😂
-END-
以上,就是今天的分享了,看完文章记得右下角给何老师点赞,也欢迎在评论区写下你的留言。