上海某公司表扬加班,榜一当月加班160小时~
昨天晚上刷到个离谱新闻😂,说上海有家公司表扬加班榜,榜一哥们当月加了159.96小时,平均每天23:12下班。作为个老码农,我脑子里第一反应不是“敬业”,而是——这工时表怎么写的,SQL 是不是得 SUM() 一下才有这种数。
你想啊,159.96小时,这相当于每晚多干五个多小时,基本等于再上了半个班。而且这种节奏,光是 CI/CD 流水线报警都得响好几轮,身体的 GC 都来不及跑完就又开始新一轮任务了。🙃
最怕的是,这种文化一旦被当成“榜样”,新来的小朋友还以为这是默认配置。可在我们行内,持续加班就像死循环里忘了 break,早晚把线程卡死。代码可以热部署,人可没法热替换啊。【备注:文末可领最新资料】
算法题:最小操作次数使数组元素相等
昨天晚上十一点多,我在公司楼下等外卖,手机一抬头就有人在群里问:哥,那个“最小操作次数使数组元素相等”怎么写啊?我脑子里一过电儿:这个别想复杂了,思路其实很生活化,像给所有人一起加工资那种…咳我跑题了,说正事。
题意一般是:一次操作把 n−1 个元素都加一(或等价地,把某一个元素减一),问最少要几次让数组全相等。答案其实就是:把所有数拉到最小值,次数等于所有元素与最小值的差的总和。写成式子就是moves = sum(nums) - min(nums) * n。 为啥不是拉到平均数?因为每次操作相当于“整体加一但留一个不动”,它和“挑一个数减一”是同一个事;为了最快收敛,大家都朝最小的那个靠拢就行。
为啥这个结论是对的
你把“n−1个加一”换个视角:等价于“挑一个数减一”。那想把所有数变相等,显然只需要把每个数都减到同一个值。减到谁最省?减到当前 最小值 不会浪费任何步,因为任何更小的目标都会多减;任何更大的目标都得给更小的那些再加回去,还是绕远路。于是每个元素贡献 a[i] - min 次,累加就是答案。这个推导不需要动归不需要贪心证明,纯操作等价想清楚就行。
口味清淡版,注意用 long 防溢出,结果要是题目保证不爆,可以再转回 int。
publicclassMinMovesEqualArray{
publicstaticlongminMoves(int[] nums){
if (nums == null || nums.length <= 1) return0L;
int n = nums.length;
int min = nums[0];
long sum = 0L;
for (int x : nums) {
sum += x;
if (x < min) min = x;
}
return sum - (long) min * n;
}
// 小测一下
publicstaticvoidmain(String[] args){
int[] a = {1, 2, 3};
System.out.println(minMoves(a)); // 3,操作序列比如:{1,2,3}->{2,3,3}->{3,3,3} 两步?别急,按等价视角是把3减到1: (3-1)+(2-1)=3 次
int[] b = {5, 5, 5};
System.out.println(minMoves(b)); // 0
}
}
有人会问,刚才示例为啥打印 3,不是两步吗?因为你脑内用的是“n−1个加一”的操作,那个走法可能两步能到;而我们公式算的是把数字都“减到最小”的总次数,这两种描述是等价的,但计数口径不同:一个是按“单点减一”累加次数,一个是按“批量加一”数轮次。真正的最小轮次正好等于上面这个总差值,二者是一回事。再一个,数组里有负数、零都没事,min 一样好用;数据量很大时别用排序,线性扫一遍更稳。时间复杂度 O(n),空间 O(1),就够快了。
我在门口把外卖拿上来,电梯里又有人问要不要用平均数/中位数,我直接摇头:这个操作不是“每次随便加减一个”,而是“锁死 n−1 个一起加一”,等价视角定了,目标就是 当前最小值。好了我先吃口饭,有坑明天再聊。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html