放弃华为16级,进了体制内一个非常清闲的部门,早八晚五,原以为会越来越好,结果发现工作没意义,工资也不好看,后悔了
刚看到个贴子:有网友吐槽,说自己放弃华为16级,跑去体制内一个特别清闲的部门,本以为日子会越过越舒服,结果发现工作像在养老,工资也一般,现在开始后悔了。
网友回帖里有说“清闲就是最大的福利”,也有人说“华为的强度不是人人扛得住”。但在我看来,这哥们的问题不是体制不好,也不是华为多香,而是预期和现实不匹配。
怎么说呢,清闲久了,人确实容易空虚;收入低久了,人也会焦虑。就像买菜一样,便宜的没味道,好吃的又心疼钱,想两头都占,只能越来越纠结。
从我的角度看,后悔不是坏事,说明他开始重新审视自己真正想要什么。体制内不一定不能发展,大厂也不是只有高压才能活。关键是找到适合自己的节奏,再做选择。【备注:文末可领最新资料】
面试题:旋转函数
昨天晚上十一点多我还在公司,正准备关电脑回家,结果我们组那个小李突然在后面喊我:东哥东哥,你懂不懂那个“旋转函数”的题啊,我这破题 O(n²) 老是超时。嗯……本来已经站起来拿包了,只能又坐回去给他画了半个白板。
先把题意思捋一下哈,用大白话说: 有个数组 nums,长度是 n,比如 [4,3,2,6]。定义一个东西叫 F(k):把数组向右旋转 k 步,然后用下标乘以对应元素求和。
比如不旋转的时候(k = 0):
还是 [4,3,2,6]F(0) = 04 + 13 + 22 + 36 = 0 + 3 + 4 + 18 = 25
右旋一步(k = 1),数组变成 [6,4,3,2]:
F(1) = 06 + 14 + 23 + 32 = 0 + 4 + 6 + 6 = 16
题目就是:所有的 F(k) 里面,最大的那个是多少。
小李一开始写的就是最直觉那种:每次真的把数组旋转一遍,然后再扫一遍算和。代码也挺“教科书”的那种,时间复杂度直接 n * n,数组一长立马超时,他人都麻了。
我当时跟他说,你想象一下,如果每次 F(k) 都从头算起,肯定浪费。关键是要找到 F(k) 和 F(k-1) 的关系,这样就能一边转一边更新结果,不用每次重来。
你看啊,先把几个量记一下:
总和 sum = nums[0] + nums[1] + ... + nums[n-1]F(0) 很好算: F(0) = 0*nums[0] + 1*nums[1] + ... + (n-1)*nums[n-1]
重点来了,F(k) 和 F(k-1) 怎么关系起来?
别急着看公式,你脑子里先过一遍旋转的画面: 右旋一次,相当于最后一个元素被挪到最前面,其他的下标都 +1。
拿 [4,3,2,6] 举个例子:
F(0):按原数组算 右旋一次得到 [6,4,3,2]是 F(1)再右旋一次 [2,6,4,3]是 F(2)
这时候可以这么想: 从 F(k-1) 变成 F(k),发生了两件事:
每个元素的下标都 +1,所以“整体”会多加一遍数组总和 sum。但是有一个倒霉孩子从下标 n-1 被挪到了下标 0,它原来贡献是 (n-1) * value,现在贡献变成0 * value,等于少了(n * value)那么多(因为刚才那一步“整体 + sum”里面已经把它算成 +value 了,要把多出来的 n*value 扣掉)。
于是就得到了那个经典关系式(我口述一下,你自己脑补下):
F(k) = F(k-1) + sum - n * nums[n - k]
注意这里 nums[n - k] 是右旋第 k 次时,被“挪到最前面”的那个元素。本质就是,右旋 k 次,其实就是把原数组最后 k 个元素搬到前面。
有了这个关系,整件事就好办了:
先把 sum求出来计算一遍 F(0) 然后从 k=1 到 n-1,用上面的递推式滚着算下去,顺手维护一个最大值
复杂度就从 O(n²) 直接变成 O(n),面试官一般看到你能把这题讲到这个程度,脸上表情都会柔和很多,哈哈。
我当时就随手给小李写了个 Java 版本,大概像下面这样,你可以直接拿去用:
publicclassRotateFunction{
// 主方法:给一个数组,返回最大旋转函数值
publicintmaxRotateFunction(int[] nums){
int n = nums.length;
if (n == 0) return0;
if (n == 1) return0; // 只有一个元素,怎么转都一样,下标永远是 0
long sum = 0; // 数组元素总和
long f0 = 0; // F(0)
for (int i = 0; i < n; i++) {
sum += nums[i];
f0 += (long) i * nums[i];
}
long max = f0;
long curr = f0; // 当前 F(k) 的值,从 k=0 开始滚
// 按照公式:F(k) = F(k-1) + sum - n * nums[n - k]
for (int k = 1; k < n; k++) {
curr = curr + sum - (long) n * nums[n - k];
if (curr > max) {
max = curr;
}
}
return (int) max;
}
// 随便写个 main 测一下
publicstaticvoidmain(String[] args){
RotateFunction rf = new RotateFunction();
int[] nums = {4, 3, 2, 6};
System.out.println(rf.maxRotateFunction(nums)); // 输出 26
}
}
顺带说一句,上面我用的是 long,不是故意装专业,纯粹是防止有些测试数据特别大,下标乘元素的时候把 int 撑爆了,踩过坑的人都懂那种“代码看着没问题但结果就是不对”的绝望。
小李看完白板推导,再看这段代码,大概五分钟就完全想明白了,然后很开心地对我说:行了东哥你快回去睡觉吧,我自己再刷两道。 我看了看时间,都快半夜了,就顺口回他一句:别刷了,早点回去休息,明天精神好一点,旋转函数也转得快一点……
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html