外包同事转正请客,大家点了4000多的菜,结账时外包同事说只付了2000,余下的大家AA,尴尬了!
刚看到个贴子,说一个外包同事转正请客,本来大家以为是好事,结果点了4000多的菜,他只付了2000,剩下的要大家AA,场面直接尴尬😅。同事们事后都说“早知道不吃了”。
我作为程序员的第一反应是:这操作就像线上服务挂了一半,还要大家一起背锅。请客是表达心意,不是搞“分布式扣费”。网友们说他小气,我觉得更像是没想明白“协议”。既然开口说“请客”,那就要承担全量费用,临时改规则就是 bug。
换个角度看,这件事也说明了职场里最怕的是“边界不清”。请客是社交契约,就像代码接口,定义了就得遵守,不然大家的信任就崩掉。AA聚餐没问题,但前提是要提前讲清楚。
所以说啊,做人跟写程序一样,规则要明确,承诺要执行。不然一次翻车,信誉分就归零。【备注:文末可领最新资料】
算法题:使数组唯一的最小增量
昨儿半夜十一点多,我在公司楼下吹风,手机还剩3%,小李在群里问我那个…“数组里有重复咋办,最少加多少次数能全不同?”就是那个题嘛,英文名差不多“使数组唯一的最小增量”。我当时脑袋有点昏,但这个思路真不难,说两句你们就懂。
你有一堆整数,允许你把任意元素+1、+1、再+1…次数随便,但每次只能加1。目标是让所有值都不重复,同时把总加法次数压到最低。听着像搬桌子往后挪,前面坐满了,就把后面那位往后挪一格,别客气。
我一般就两个字:排序。为啥?因为排完序之后你从左往右看,每个数只需要和“前一个已经安顿好的数”比一下。如果它小了或者撞车了,就把它抬到“前一个数+1”的位置,这样最省。像排队打饭,前面那哥们站7号位,你不可能塞到6,你就老老实实去8。注意我们只记代价差:抬到哪就加几次。
import java.util.*;
publicclassMinIncrementUnique{
publicintminIncrementForUnique(int[] nums){
Arrays.sort(nums);
long moves = 0; // 防止溢出,最后转回int也行
int need = Integer.MIN_VALUE; // 当前这个位置至少要到达的值
for (int x : nums) {
if (need == Integer.MIN_VALUE) {
need = x; // 第一位,随它
} elseif (x <= need) {
moves += (need + 1 - x);
need = need + 1;
} else {
need = x; // 不用动,直接占位
}
}
return (int)moves;
}
// 小测一把
publicstaticvoidmain(String[] args){
MinIncrementUnique s = new MinIncrementUnique();
System.out.println(s.minIncrementForUnique(newint[]{3,2,1,2,1,7})); // 6
System.out.println(s.minIncrementForUnique(newint[]{1,1,1})); // 3
System.out.println(s.minIncrementForUnique(newint[]{0})); // 0
}
}
就是贪心。排好序以后,你每次只把当前数抬到刚好不冲突的位置——比这更少的增量做不到,因为前面的位置都被占了,往后多一步都是浪费。等我刚才上楼时电梯卡了一下,我还在想这个“need”的变量,其实就是“下一个可用的最小号码”。每走一个人,你更新need,要么跟着前一个+1,要么被当前数本身刷新。
时间是O(n log n),主要花在排序;空间O(1)或O(log n)(看排序实现)。有人问会不会溢出?数组值要是很大,累计moves可能超int,所以我用long累加,再cast回去。还有个边角:数组全是同一个数,比如全1,那就形成1、2、3…一路推,代价是0+1+2…,公式自己心里有数,代码自然算出来。
还有别的玩法吗
有。要是数值范围不大,你可以搞个“计数+搬砖”的思路:把多出来的重复当作“待安置人口”,从小到大扫,空位就塞一个,多的继续往后推,像挪车一样。复杂度能到O(n+range)。但通用场景,排序贪心更省心,写法也不容易翻车。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html