组里有个 35岁的老员工,技术一般,干了7年,月薪 16k,上周领导找我说,要把他转岗到测试组,不同意就优化掉~
刚看到个贴子,说组里有个35岁老员工,35岁,干了7年,技术一般,拿16k。领导让他转岗去测试,不去就优化,人家还有两娃、老婆不工作、房贷15年,听着确实挺扎心的。
我同情他的处境,但也得承认,35岁技术停在“还行”,在现在的行情里,本来就很危险。公司做选择,看的是“现在能创造多少价值”,不会管你房贷和孩子。
转岗测试,说好听点是给条路,难听点是最后的缓冲期。真要我建议他,先稳住饭碗,边干边补课,看看能不能在测试里做深做专,或者利用这段时间找下一家。
说到底,家庭越重,越不能只想着“别动我这份工作”,而是要提前给自己多准备几条路。
面试题:宝石与石头
你有没有这种感觉啊,下班地铁上,人挤人、脑袋又昏,又被同事甩来一道“简单算法题”,嘴上说简单,手上就是写不顺那种。 “宝石与石头”这个题就挺典型的,逻辑很直白,但要说清楚、写优雅,用 Java 写得好看一点,也还是有点讲究的。
先把题目说人话版
题意就是: 有两个字符串:
jewels:哪些字符算“宝石类型”,比如"aA"代表小写 a 和大写 A 是宝石stones:你手上一堆石头,比如"aAAbbbb"
问:stones 里,一共出现了多少个“宝石”? 比如 jewels = "aA", stones = "aAAbbbb"那里面有:a A A 三个,是宝石,所以答案是 3。
有几个点要注意一下哈:
字符大小写是区分的, 'a'和'A'是两种宝石jewels里面不会有重复字符只要 stones 的某个字符“在 jewels 中存在”,就算一个宝石
你可以脑补成:jewels 是「你喜欢的字母」,stones 是「弹幕」,数一数整屏弹幕里有多少你喜欢的字母,差不多这个意思。
小思路:暴力和小聪明的区别
最直接的方法你肯定也能想到: 对 stones 里的每一个字符,去 jewels 里挨个比对,看是不是宝石。
伪代码脑补一下:
对 stones 逐个字符 s:
一样就计数 +1 再对 jewels 逐个字符 j:
时间复杂度大概是 O(m * n),m 是 stones 长度,n 是 jewels 长度。 数据量不大也能跑,但有点“直男写法”,能优化一下。
稍微动点脑子:jewels 其实更像是一个“集合”——只要问一个问题:这个字符是不是在集合里?
那 Java 里面啥适合干这个?HashSet<Character>。
把 jewels 每个字符丢到一个 HashSet 里,然后扫描 stones,遇到一个字符,O(1) 时间判断是不是在 set 里,是就计数 +1。 整体时间复杂度就接近 O(m + n),写起来也挺顺手。
Java 实现代码(核心逻辑)
直接上代码,你可以丢到本地跑一下:
publicclassJewelsAndStones{
/**
* 统计 stones 里面有多少字符是 jewels 里的“宝石”
*/
publicintnumJewelsInStones(String jewels, String stones){
if (jewels == null || stones == null) {
return0;
}
// 1. 把所有宝石类型丢进一个 Set,方便快速判断
java.util.Set<Character> jewelSet = new java.util.HashSet<>();
for (int i = 0; i < jewels.length(); i++) {
jewelSet.add(jewels.charAt(i));
}
// 2. 遍历 stones,遇到属于宝石集合的就 +1
int count = 0;
for (int i = 0; i < stones.length(); i++) {
char c = stones.charAt(i);
if (jewelSet.contains(c)) {
count++;
}
}
return count;
}
// 简单 main 测试一下
publicstaticvoidmain(String[] args){
JewelsAndStones solution = new JewelsAndStones();
String jewels = "aA";
String stones = "aAAbbbb";
int result = solution.numJewelsInStones(jewels, stones);
System.out.println("宝石个数 = " + result); // 预期输出 3
}
}
这个写法其实就几个点:
先建一个 Set把宝石类型记下来遍历 stones,逐个查 set 查到就 +1,最后返回计数
没有多余花活,可读性也还算不错。
顺带聊两句细节优化
你要是面试的时候,面试官继续追问,你可以再展开一点,不要只停留在“我会写代码”这个层面。
比如:
为什么用
HashSet? 因为它contains平均时间复杂度是 O(1),适合做“存在性判断”。能不能用数组代替 set? 可以,如果题目保证只会出现 ASCII 字符,你可以用一个
boolean[128]或boolean[256]数组:flag[c] = true表示 c 是宝石,判断的时候if (flag[stones.charAt(i)])就行。 性能会再快一点,但可读性稍差一点,看个人偏好和场景。
大概写法是这样:
publicintnumJewelsInStonesByArray(String jewels, String stones){
if (jewels == null || stones == null) {
return0;
}
// 简单假设字符在 0~127 范围内
boolean[] isJewel = newboolean[128];
for (int i = 0; i < jewels.length(); i++) {
char c = jewels.charAt(i);
if (c < 128) {
isJewel[c] = true;
}
}
int count = 0;
for (int i = 0; i < stones.length(); i++) {
char c = stones.charAt(i);
if (c < 128 && isJewel[c]) {
count++;
}
}
return count;
}
这个更像是“比赛写法”,追求一点点极致性能;平时工作里,HashSet 就够用了。
再扯回到实际刷题 / 面试怎么说
如果你是坐在面试官对面,被问到这题,你可以按这个节奏说话:
先复述题意,确认没听错 提一句最暴力的解法:两层循环 紧接着说:可以用 HashSet把 jewels 存起来,把时间复杂度降到 O(m+n)边说边写上面那段 Java 代码 有余力再补一句:如果字符集有限,也可以用数组当哈希表
这样一套下来,比你直接上去就写 for 循环,看起来专业很多。
行了,这个题基本就这样,挺适合热身或者给自己练手写的,你可以自己改几个用例试试:jewels 为空、stones 为空、只有一个字符那种,看结果是不是符合直觉。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html