程序员老鬼

组里有个 35岁的老员工,技术一般,干了7年,月薪 16k,上周领导找我说,要把他转岗到测试组,不同意就优化掉~

刚看到个贴子,说组里有个35岁老员工,35岁,干了7年,技术一般,拿16k。领导让他转岗去测试,不去就优化,人家还有两娃、老婆不工作、房贷15年,听着确实挺扎心的。

Image

我同情他的处境,但也得承认,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
    }
}

这个写法其实就几个点:

  1. 先建一个 Set 把宝石类型记下来
  2. 遍历 stones,逐个查 set
  3. 查到就 +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

最后给大家分享一份不错的副业资料,点击下方公众号,回复关键字: 副业 领,也可以链接我微信:hls404