虚报了薪资流水入职后,公司要把我开除!每月薪资10000不到 我说我每个月25000
我在网上看到一个帖子,有人吐槽:面试时把工资吹高了,实际月薪一万不到,硬说自己有2万5,想冲3万。结果公司真给了offer,报道时又要求交一年薪资流水,这下好了,牛皮吹出去,回旋镖嗖一下就飞回来了。
面试想抬价,能理解,谁不想多挣点钱啊,打工人看到工资数字,眼睛都能亮两度。但你一下从一万吹到两万五,这就不是包装了,这是给自己开了美颜十级滤镜。公司这边也不算厚道,真有疑问早点说,别等人入职了再翻桌子。
说到底,找工作这事还是别玩太大,薪资可以谈,话不能飘,不然最后班没上稳,仲裁还得自己跑,纯纯给生活加了个副本。
面试题:有序转化数组
这题我第一次看到的时候,直觉很容易写成两步:
先把数组里每个数都代进公式 f(x) = ax² + bx + c,再整体排个序。
代码不复杂,但这题既然给了原数组有序这个条件,基本就在提醒你:别直接把它浪费掉。
先看一个最直接、也最容易想到的写法:
publicint[] sortTransformedArray(int[] nums, int a, int b, int c) {
int[] ans = newint[nums.length];
for (int i = 0; i < nums.length; i++) {
ans[i] = calc(nums[i], a, b, c);
}
Arrays.sort(ans);
return ans;
}
privateintcalc(int x, int a, int b, int c){
return a * x * x + b * x + c;
}
能过,但味道不太对。时间复杂度是 O(n log n),而这题其实能做到 O(n)。
关键点不在公式本身,而在二次函数图像。
先看函数开口方向
公式是:
f(x) = ax * x + b * x + c
如果 a > 0,抛物线开口向上,离对称轴越远,函数值越大。 如果 a < 0,抛物线开口向下,离对称轴越远,函数值越小。
而原数组 nums 本身已经升序。
这时候有个很实用的判断:数组两端的元素,往往会产生当前最大值或者最小值。
所以这题的做法其实很像“有序数组平方”那道题,都是双指针。
为什么两端能决定答案
拿 a > 0 举例。
抛物线开口向上,越靠近两边,值越大。 所以此时转换后的最大值,一定更可能出现在 nums[left] 或 nums[right] 里。
那就可以这样做:
左右指针分别指向数组两端 比较两端代入函数后的值 谁大,谁就放到结果数组的末尾 指针往中间收缩
如果 a < 0 呢?
这时候开口向下,两端反而更小。 那就把较小的值放到结果数组开头。
这一步想通,代码就顺了。
publicclassSolution{
publicint[] sortTransformedArray(int[] nums, int a, int b, int c) {
int n = nums.length;
int[] ans = newint[n];
int left = 0;
int right = n - 1;
int idx = a >= 0 ? n - 1 : 0;
while (left <= right) {
int lv = transform(nums[left], a, b, c);
int rv = transform(nums[right], a, b, c);
if (a >= 0) {
if (lv > rv) {
ans[idx--] = lv;
left++;
} else {
ans[idx--] = rv;
right--;
}
} else {
if (lv < rv) {
ans[idx++] = lv;
left++;
} else {
ans[idx++] = rv;
right--;
}
}
}
return ans;
}
privateinttransform(int x, int a, int b, int c){
return a * x * x + b * x + c;
}
}
拿一组数据走一下
比如:
nums = [-4, -2, 2, 4]
a = 1, b = 3, c = 5
函数是:
f(x) = x^2 + 3x + 5
两端先算:
f(-4) = 9
f(4) = 33
因为 a > 0,大的先放后面,所以 33 先进结果数组末尾。
接着继续比较,直到收敛。
最后得到:
[3, 9, 15, 33]
整个过程没有额外排序,指针只扫一遍。
这题真正容易卡的地方
不是双指针本身,而是填充方向。
很多人写到一半会乱:
a >= 0时,结果从后往前填a < 0时,结果从前往后填
这个地方一旦反了,结果要么逆序,要么还得再来一次排序,那就白做了。
还有一个细节,判断里我写的是 a >= 0,不是单纯 a > 0。 因为 a == 0 时,函数退化成一次函数:
f(x) = bx + c
这时候虽然不是抛物线了,但按这个逻辑照样能处理,不需要单独拆分分支。
复杂度
这题优化后的复杂度很干净:
时间复杂度:O(n)
空间复杂度:O(n)
空间这里没法省掉,因为题目本身就要返回新数组。
这题看着是数学题,落到代码上其实还是双指针。 题目里只要出现“原数组有序”,通常都值得先停一下,看看能不能少一次 sort。 这一步想到了,题就已经做完一半了。