刚看到个贴子,说有网友面试一个开口就要28K的程序员。简历上写着“精通Linux/Shell”,结果面试官让他现场写个统计Nginx日志里访问量Top10 IP的命令,他憋半天只敲出来个cat,后面啥也写不出来。

网友们的回帖我看了看,有笑他是“会cd就叫精通”的,也有替他说话的,说现场紧张、命令记不住很正常,还有人吐槽现在面试爱出偏题、故意为难人。
我觉得这事吧,问题关键不在那一道命令,而在“价码”和“实力”能不能对得上。你要价28K,那起码得把常用工具链练成肌肉记忆,否则就是拿高配置的价,干入门级的活。另一方面,面试官也别太得意,真正在公司干活,不是背命令,是解决问题。
说到底还是:标注能力别虚高,要价之前先看看自己值不值这个数,踏实学点真本事,比什么花哨词儿都硬。
算法题:整数转罗马数字
那天晚上十一点多,我在工位那边磨叽着刷题,旁边小伙子突然来一句:哥,这个“整数转罗马数字”什么鬼啊,看着简单写出来一堆 bug。正好我也困得不行,就一边喝口凉掉的咖啡,一边给他用 Rust 把这个算发…算法过了一遍。
先说下罗马数字是啥意思哈,别一上来就写代码。罗马数字只有几个符号: I=1,V=5,X=10,L=50,C=100,D=500,M=1000。 但它还有点“减法规则”: 比如 4 不是 IIII,而是 IV(5-1); 9 是 IX(10-1); 40 是 XL;90 是 XC;400 是 CD;900 是 CM。 面试官常考的就是你能不能把这些组合处理干净。
小伙子一开始的思路特别直男:从千位、百位、十位、个位一个个拆,然后自己写一堆 if/else,什么“如果百位是 3 就拼 CCC”这种。写到后面,自己都看不懂了。其实这个题更顺手的写法,是“贪心”:每次尽量用最大的罗马数字往上凑。
简单说下贪心的想法,就是先准备一张从大到小的“对照表”,包括那些减法形式,一口气都列进去:
思路就很好记了: 给你一个 num,一直从最大的 1000 开始看,如果 num ≥ 1000,就拼一个 "M",num 减 1000;还能减就继续。减不动了就看下面 900,能减就拼 "CM"……一直往下走,最后 num 会变成 0,拼出来的字符串就是答案。
为啥这个贪心不会出错?因为:
说完人话,整点 Rust 代码,小伙子当场就抄走了:
fnint_to_roman(mut num: i32) -> String {// 从大到小的数值和对应符号let values = [1000, 900, 500, 400,100, 90, 50, 40,10, 9, 5, 4, 1];let symbols = ["M", "CM", "D", "CD","C", "XC", "L", "XL","X", "IX", "V", "IV", "I"];letmut res = String::new();// 逐个尝试从 num 里“扣掉”这些数for (v, s) in values.iter().zip(symbols.iter()) {while num >= *v { res.push_str(s); num -= *v; } } res}fnmain() {let tests = [3, 4, 9, 58, 1994];for n in tests {let roman = int_to_roman(n);println!("{} -> {}", n, roman); }}跑一下,大概输出是这样的(别纠结顺序格式哈):
这个实现有几个小点你可以顺手记一下:
第一,num 用 mut,因为我们一直在往下减。 第二,values 和 symbols 用同样顺序,然后 zip 一下,for 循环里就不会写错对应关系。 第三,时间复杂度其实很稳,values 就 13 个数字,每个最多循环几次,num 最大也就 3999,这点操作在面试题里可以忽略不计。
那天我把代码给小伙子看,他愣了一下说:原来可以不用想“几千几百几十个”的那种拆法,直接这么扣就完事了。然后他又打开下一道题,我准备去倒杯水…结果杯子都还没洗干净,测试那边又来催 log 了,先忙活别的去了。