xhs
秋招卡学历,挂简历的事儿,年年有,今年来得特别快。
最近看到一篇帖子,贴主吐槽,自己本科 985,硕士华五,既有大模型论文,也有对口的大模型算法实习经历,但最后连简历都没过。
这位同学投递的是 2025 校招的「通用大模型算法工程师」,按理说,这样的履历至少值得一次笔试机会,结果是以「简历挂」为收尾。
不是,现在的互联网大厂都已经供过于求到这个程度了吗?
但从评论区来看,最近这样的事儿并不少见。
底下有西电和浙大的同学留言,表示有种在招"超人"的感觉,甚至有"2A1B"的同学也被挂简历,连"6A一作"的同学都称正在泡池子 🤣🤣🤣
评论区唯一一个拿到该公司社区算法岗笔试机会的同学,是清华出身的:
有时候很难分清,是这些公司没 HC 不想招人,还是说真的某些岗位已经卷到博士起步了。
对此,你怎么看?
...
回归主题。
来一道和「xhs」相关的题目。
题目描述
平台:LeetCode
题号:213
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。
这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。
同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
示例 1:
输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
示例 2:
输入:nums = [1,2,3,1]
输出:4
解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
示例 3:
输入:nums = [0]
输出:0
提示:
动态规划
在 198. 打家劫舍 中,并没有「第一间」和「最后一间」不能同时选择的限制,因此我们从头到尾做一遍 DP 即可。
在 198. 打家劫舍 中,我们可以将状态定义为两维:
代表考虑前 个房间,当前 房间的现在状态为 的最大价值。
-
代表考虑前 个房间,并且「不选」第 个房间的最大价值。由于已经明确了第 个房间不选,因此 可以直接由 转移而来。
-
代表考虑前 个房间,并且「选」第 个房间的最大价值。由于已经明确了第 个房间被选,因此 直接由 转移过来。
到这里,你已经解决了 198. 打家劫舍 了。
对于本题,由于只是增加了「第一间」和「最后一间」不能同时选择的限制。
通常,对于一些明显不是「增加维度」的新限制条件,我们应当考虑直接将其拎出讨论,而不是多增加一维进行状态记录。
我们可以把「第一间」&「最后一间」单独拎出来讨论:
-
明确「不选」第一间:
-
初始化 和 ,均为 。 -
先从「第二间」开始递推到「倒数第二间」的最大价值。 -
再处理「最后一间」的情况:由于明确了「不选第一间」,则最后的最大价值为 。
-
-
允许「选」第一间:
-
初始化 和 ,分别为 和 。 -
先从「第二间」开始递推到「倒数第二间」的最大价值。 -
再处理「最后一间」的情况:由于明确了「选第一间」,则最后的最大价值为 。
-
走完两遍 DP 后,再从两种情况的最大价值中再取一个 即是答案。
Java 代码:
class Solution {
public int rob(int[] nums) {
int n = nums.length;
if (n == 0) return 0;
if (n == 1) return nums[0];
// 第一间「必然不选」的情况
int[][] f = new int[n][2];
for (int i = 1; i < n - 1; i++) {
f[i][0] = Math.max(f[i - 1][0], f[i - 1][1]);
f[i][1] = f[i - 1][0] + nums[i];
}
int a = Math.max(f[n - 2][1], f[n - 2][0] + nums[n - 1]);
// 第一间「允许选」的情况
f[0][0] = 0; f[0][1] = nums[0];
for (int i = 1; i < n - 1; i++) {
f[i][0] = Math.max(f[i - 1][0], f[i - 1][1]);
f[i][1] = f[i - 1][0] + nums[i];
}
int b = Math.max(f[n - 2][0], f[n - 2][1]);
return Math.max(a, b);
}
}
C++ 代码:
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
if (n == 0) return 0;
if (n == 1) return nums[0];
vector<vector<int>> f(n, vector<int>(2, 0));
for (int i = 1; i < n - 1; i++) {
f[i][0] = max(f[i - 1][0], f[i - 1][1]);
f[i][1] = f[i - 1][0] + nums[i];
}
int a = max(f[n - 2][1], f[n - 2][0] + nums[n - 1]);
f[0][0] = 0; f[0][1] = nums[0];
for (int i = 1; i < n - 1; i++) {
f[i][0] = max(f[i - 1][0], f[i - 1][1]);
f[i][1] = f[i - 1][0] + nums[i];
}
int b = max(f[n - 2][0], f[n - 2][1]);
return max(a, b);
}
};
Python 代码:
class Solution:
def rob(self, nums: List[int]) -> int:
n = len(nums)
if n == 0: return 0
if n == 1: return nums[0]
f = [[0, 0] for _ in range(n)]
for i in range(1, n - 1):
f[i][0] = max(f[i - 1][0], f[i - 1][1])
f[i][1] = f[i - 1][0] + nums[i]
a = max(f[n - 2][1], f[n - 2][0] + nums[n - 1])
f[0][0] = 0; f[0][1] = nums[0]
for i in range(1, n - 1):
f[i][0] = max(f[i - 1][0], f[i - 1][1])
f[i][1] = f[i - 1][0] + nums[i]
b = max(f[n - 2][0], f[n - 2][1])
return max(a, b)
TypeScript 代码:
function rob(nums: number[]): number {
const n: number = nums.length;
if (n === 0) return 0;
if (n === 1) return nums[0];
const f: number[][] = new Array(n).fill(0).map(() => [0, 0]);
for (let i: number = 1; i < n - 1; i++) {
f[i][0] = Math.max(f[i - 1][0], f[i - 1][1]);
f[i][1] = f[i - 1][0] + nums[i];
}
let a: number = Math.max(f[n - 2][1], f[n - 2][0] + nums[n - 1]);
f[0][0] = 0; f[0][1] = nums[0];
for (let i: number = 1; i < n - 1; i++) {
f[i][0] = Math.max(f[i - 1][0], f[i - 1][1]);
f[i][1] = f[i - 1][0] + nums[i];
}
let b: number = Math.max(f[n - 2][0], f[n - 2][1]);
return Math.max(a, b);
};
-
时间复杂度: -
空间复杂度:
空间优化
不难发现,我们状态转移最多依赖到前面的 1 行,因此可以通过很机械的「滚动数组」方式将空间修改到 。
Java 代码:
class Solution {
public int rob(int[] nums) {
int n = nums.length;
if (n == 0) return 0;
if (n == 1) return nums[0];
// 第一间「必然不选」的情况
int[][] f = new int[2][2];
for (int i = 1; i < n - 1; i++) {
f[i%2][0] = Math.max(f[(i - 1)%2][0], f[(i - 1)%2][1]);
f[i%2][1] = f[(i - 1)%2][0] + nums[i];
}
int a = Math.max(f[(n - 2)%2][1], f[(n - 2)%2][0] + nums[n - 1]);
// 第一间「允许选」的情况
f[0][0] = 0; f[0][1] = nums[0];
for (int i = 1; i < n - 1; i++) {
f[i%2][0] = Math.max(f[(i - 1)%2][0], f[(i - 1)%2][1]);
f[i%2][1] = f[(i - 1)%2][0] + nums[i];
}
int b = Math.max(f[(n - 2)%2][0], f[(n - 2)%2][1]);
return Math.max(a, b);
}
}
C++ 代码:
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
if (n == 0) return 0;
if (n == 1) return nums[0];
vector<vector<int>> f(2, vector<int>(2, 0));
for (int i = 1; i < n - 1; i++) {
f[i % 2][0] = max(f[(i - 1) % 2][0], f[(i - 1) % 2][1]);
f[i % 2][1] = f[(i - 1) % 2][0] + nums[i];
}
int a = max(f[(n - 2) % 2][1], f[(n - 2) % 2][0] + nums[n - 1]);
f[0][0] = 0; f[0][1] = nums[0];
for (int i = 1; i < n - 1; i++) {
f[i % 2][0] = max(f[(i - 1) % 2][0], f[(i - 1) % 2][1]);
f[i % 2][1] = f[(i - 1) % 2][0] + nums[i];
}
int b = max(f[(n - 2) % 2][0], f[(n - 2) % 2][1]);
return max(a, b);
}
};
Python 代码:
class Solution:
def rob(self, nums: List[int]) -> int:
n = len(nums)
if n == 0: return 0
if n == 1: return nums[0]
f = [[0, 0] for _ in range(2)]
for i in range(1, n - 1):
f[i % 2][0] = max(f[(i - 1) % 2][0], f[(i - 1) % 2][1])
f[i % 2][1] = f[(i - 1) % 2][0] + nums[i]
a = max(f[(n - 2) % 2][1], f[(n - 2) % 2][0] + nums[n - 1])
f[0][0] = 0; f[0][1] = nums[0]
for i in range(1, n - 1):
f[i % 2][0] = max(f[(i - 1) % 2][0], f[(i - 1) % 2][1])
f[i % 2][1] = f[(i - 1) % 2][0] + nums[i]
b = max(f[(n - 2) % 2][0], f[(n - 2) % 2][1])
return max(a, b)
TypeScript 代码:
function rob(nums: number[]): number {
const n: number = nums.length;
if (n === 0) return 0;
if (n === 1) return nums[0];
const f: number[][] = [[0, 0], [0, 0]];
for (let i: number = 1; i < n - 1; i++) {
f[i % 2][0] = Math.max(f[(i - 1) % 2][0], f[(i - 1) % 2][1]);
f[i % 2][1] = f[(i - 1) % 2][0] + nums[i];
}
let a: number = Math.max(f[(n - 2) % 2][1], f[(n - 2) % 2][0] + nums[n - 1]);
f[0][0] = 0; f[0][1] = nums[0];
for (let i: number = 1; i < n - 1; i++) {
f[i % 2][0] = Math.max(f[(i - 1) % 2][0], f[(i - 1) % 2][1]);
f[i % 2][1] = f[(i - 1) % 2][0] + nums[i];
}
let b: number = Math.max(f[(n - 2) % 2][0], f[(n - 2) % 2][1]);
return Math.max(a, b);
};
-
时间复杂度: -
空间复杂度:
最后
巨划算的 LeetCode 会员优惠通道目前仍可用 ~
使用福利优惠通道 leetcode.cn/premium/?promoChannel=acoier,年度会员 有效期额外增加两个月,季度会员 有效期额外增加两周,更有超大额专属 🧧 和实物 🎁 福利每月发放。
我是宫水三叶,每天都会分享算法知识,并和大家聊聊近期的所见所闻。
欢迎关注,明天见。
更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉