某HR:有个候选人本来已经准备给他发 offer了,结果他大嘴巴离职前到处说,导致他同事打电话到我们公司说他人品很差,最终被放弃了
这哥们儿也太沉不住气了。
事情大概是这样,一个候选人面试都快走完了,HR那边本来已经准备给他发 offer。结果他还没正式离职呢,就在原公司到处嚷嚷,说自己要走了,可能还带点“我找到下家了”的那种劲儿。
然后离谱的来了,他同事不知道是有仇还是实在看不惯,直接打电话到新公司,说这个人人品不行。HR一听,得,那 offer 也别发了,人直接放弃。
这事听着像瓜,但其实挺职场的。很多人一拿到点风声,就开始提前庆祝,觉得自己已经上岸了。问题是,offer 没到手,入职没完成,甚至背调都没结束,你就别把嘴开那么大
有些话真不是不能说,是别太早说。尤其离职前那几天,低调点,安静点,把交接做好,比啥都强。毕竟你也不知道,办公室里谁正憋着一口气呢。
大样本统计,别把样本还原成数组
count[i] 里面放的是数字 i 出现了多少次。
这题我第一眼就不太信那种“先把所有样本塞回数组,再排序统计”的写法。题目都叫大样本了,说明数据量可能很大。你真去展开,内存先不答应,时间也没必要浪费。
真正要看的东西就这几个:
最小值、最大值、平均值、中位数、众数。
除了中位数稍微绕一点,其他都能一遍扫出来。
比如 count[7] = 3,意思不是有一个 7,而是有三个 7。平均值要加的是 7 * 3,总数要加的是 3。这个地方写错,后面结果全歪。
我一般会先把基础统计扫出来:
classSolution{
publicdouble[] sampleStats(int[] count) {
int min = -1;
int max = -1;
int mode = 0;
long total = 0;
long sum = 0;
int modeCnt = 0;
for (int v = 0; v < count.length; v++) {
int c = count[v];
if (c == 0) {
continue;
}
if (min == -1) {
min = v;
}
max = v;
total += c;
sum += (long) v * c;
if (c > modeCnt) {
modeCnt = c;
mode = v;
}
}
double mean = sum * 1.0 / total;
double median = findMedian(count, total);
returnnewdouble[]{
min,
max,
mean,
median,
mode
};
}
privatedoublefindMedian(int[] count, long total){
if ((total & 1) == 1) {
return findKth(count, total / 2 + 1);
}
long left = total / 2;
long right = left + 1;
return (findKth(count, left) + findKth(count, right)) / 2.0;
}
privateintfindKth(int[] count, long k){
long seen = 0;
for (int v = 0; v < count.length; v++) {
seen += count[v];
if (seen >= k) {
return v;
}
}
return -1;
}
}
这里中位数我用的是第 k 个数,不展开数组,只靠累计次数往前走。
举个简单点的例子:
count[1] = 2;
count[3] = 1;
count[5] = 2;
真实样本其实是:
1, 1, 3, 5, 5
但代码里不会真的生成这个数组。
找第 3 个数时,从小到大扫:
1 出现 2 次,累计到 2,还不够。
3 出现 1 次,累计到 3,够了。
所以第 3 个数就是 3,中位数也是 3。
这题容易翻车的地方有两个。
一个是平均值别用 int 算。v * count[v] 看着小,样本量一大就可能溢出,所以我这里直接转成 long。
另一个是偶数个样本的中位数。不是随便找一个位置,而是找中间两个位置,再取平均值。
这类题别想着炫技巧。桶都已经给你了,就顺着桶统计。少搬一次数据,代码反而更稳。