昨天面了一个比我大8岁的前辈,某大厂前P7,曾经年薪百万的大佬。但他坐在我对面谈薪资时那种小心翼翼的眼神,让我心里特别不是滋味。
刚看到个贴子,说一位网友去面试,面前坐着的是比他大八岁的前大厂P7。聊到薪资,对方小心翼翼地说自己20k就行,不挑活也能加班,因为已经失业快一年了。网友说,那一刻像看见了七年后的自己。
我觉得这画面挺扎心,但真不意外。红利没了,“大佬”跟不上节奏,很快就会被市场抛下。评论区很多人感慨大厂光环不值钱了,我倒觉得,真正值钱的还是你有没有持续拿出结果的能力,别把头衔当护身符。
换个角度看,这位前辈起码愿意放下面子、低预期求一份工作。普通人在职场别神话平台和title,趁还有机会多存点钱,多练几门吃饭的本事。风向怎么吹我们管不了,但只要愿意弯腰、肯更新自己,被卷来卷去,也总能再站起来。
面试题:盛最多水的容器
昨天晚上十一点多,我正准备关电脑回家,我们组那个小李突然蹭过来一句:“东哥,你会那个装水的题不?就两个竖线能装最多水那个。”我一看他那表情,就知道八成又是被算法题支配的恐惧了 😂
先说下题目是啥哈,别一上来就上代码。题目大概是这样: 给你一个 int 数组 height,每个下标 i 上是一根竖着的柱子,高度是 height[i],宽度统一算 1。你可以随便选两根柱子当容器的两边,中间当底,能装的水就是:
宽度:两根柱子之间的距离 j - i高度:取矮的那根 min(height[i], height[j])
面积 = 宽度 × 高度,你要找最大的那一组面积是多少。
小李一开始想得特别直接:暴力呗,两个 for 循环全算一遍:
publicintmaxAreaSlow(int[] height){
if (height == null || height.length < 2) return0;
int n = height.length;
int ans = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int h = Math.min(height[i], height[j]);
int w = j - i;
ans = Math.max(ans, h * w);
}
}
return ans;
}
看着挺对,是不是,对吧?问题是,时间复杂度 O(n²),面试官一看你这个解法,脸上笑嘻嘻,心里 MMP。数组长度一上来 1e5,直接超时,连测试数据都跑不完。
我就跟他说,这题其实是典型的“双指针思路”,写出来就一眼看上去很秀那种,但原理一点也不玄学。
你可以脑补一下: 把所有柱子画在一条直线上,我们先别装什么“聪明”,就先把最左边和最右边两根柱子拿来当边界。
左指针 left = 0右指针 right = n - 1
这时候能装的水面积是多少?area = (right - left) * min(height[left], height[right])
重点来了:下一步你要怎么动指针?
很多人会犹豫:我是不是要尝试所有可能?其实不用。 有一个特别关键的观察:
每一步,只移动“矮的那一边”的指针,才有可能变大;移动高的那边,只会更糟。
为啥呢,我用很口水的话说一下哈:
你把两根柱子固定住,面积 = 底 × 高
你往中间移动任意一边,底一定变小(距离变近了)
想让面积变大,只能指望“高变大”能弥补“底变小”
那你想想:
底变小 ✔ 高度还得由更矮的那根决定(因为高度取 min 啊) 也就是说,新的高度不会比原来的高 那面积就是:底变小,高不变或更矮,只会更小 如果你动的是那根更高的柱子
所以,动高的那边完全没意义
所以,每一步我们都只做一件事:
height[left] < height[right]👉 左边更矮,那就left++否则 👉 right--
一路两头往中间夹,顺便更新一下当前最大面积就行了。
代码其实非常短,小李看完直接“卧槽这也太简洁了”:
publicclassSolution{
publicintmaxArea(int[] height){
if (height == null || height.length < 2) {
return0;
}
int left = 0;
int right = height.length - 1;
int ans = 0;
while (left < right) {
int h = Math.min(height[left], height[right]);
int w = right - left;
int area = h * w;
if (area > ans) {
ans = area;
}
// 关键的移动策略:永远移动较矮的那一边
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
return ans;
}
// 随便写个 main 方便你本地跑一下
publicstaticvoidmain(String[] args){
Solution s = new Solution();
int[] height = {1, 8, 6, 2, 5, 4, 8, 3, 7};
System.out.println(s.maxArea(height)); // 输出 49
}
}
你要是还不太有感觉,可以手动在纸上走几步,比如上面这个经典数组:
一开始:
left=0高 1,right=8高 7面积 = min(1, 7) * (8 - 0) = 1 * 8 = 8左边更矮,所以 left++然后:
left=1高 8,right=8高 7面积 = min(8, 7) * 7 = 7 * 7 = 49→ 目前最大值右边更矮, right--再往里缩,面积会一会儿变大一会儿变小,但 49 就一直保留到最后
中间具体每一步就不全算了,你哪天在地铁上无聊,可以自己拿手机记事本算一算,挺解压的。
-END-
我为大家打造了一份AI教程,完全免费:songshuhezi.com/rpa.html