程序员老鬼

小公司根本就不欢迎大厂离职人…

前两天看到一条评论:“小公司根本就不欢迎大厂离职的人。”仔细一想,好像……确实挺有道理的🤔。

Image

我之前有个同事就是从某大厂出来的,简历上写满了高大上的项目名,进我们这小厂的时候,公司人都挺激动的,觉得终于抱上技术大腿了🐶。

结果两个月不到,项目黄了。

为啥?他只会做他原来那块,而且特别依赖流程、配合、工具支持,一到我们这啥都不配的野路子环境,整个人直接宕机。 

说到底,小公司图的就是一个“啥都会一点”的万金油,前端能撸,后端能补,运维出了事你还能上——你精专没错,但你要是只精专一块,其它都说“不属于我的职责范围”,那对不起,小厂真的请不起你。

所以别动不动拿“我从大厂来”当护身符,在小厂,能干活才是王道。 【备注:文末可领最新资料】

算法题:火星词典

说到“火星词典”这个算法题,老实讲,我第一反应是:“又一个异星人发明的破语言要我来解析?”不过也正是这种看似离谱的题目,才最容易卡住一堆面试者。

问题描述挺简单:给你一堆“火星文”的单词表,它们的字典序是按照火星文排列的。你要根据这些单词,推出火星文字母之间的先后关系。其实本质是啥?就是拓扑排序。

拓扑排序这种东西,听着高大上,其实就是“我排你后面”的一种链式关系解析。举个不那么正经的例子:如果产品经理说“登录页先做,支付页后做”,那这就是一个方向关系。如果你老板又说“支付前必须实名认证”,那你自然知道认证也得在支付前。一堆这样的“必须在谁之前”的依赖关系,一搞,就成了拓扑排序。

回到正题,我们先来撸下题目的套路:

public String alienOrder(String[] words){
    Map<Character, Set<Character>> graph = new HashMap<>();
    Map<Character, Integer> indegree = new HashMap<>();

for (String word : words) {
for (char c : word.toCharArray()) {
            graph.putIfAbsent(c, new HashSet<>());
            indegree.putIfAbsent(c, 0);
        }
    }

for (int i = 0; i < words.length - 1; i++) {
        String w1 = words[i], w2 = words[i + 1];
if (w1.length() > w2.length() && w1.startsWith(w2)) return""; // 坑点:非法字典序

for (int j = 0; j < Math.min(w1.length(), w2.length()); j++) {
char c1 = w1.charAt(j), c2 = w2.charAt(j);
if (c1 != c2) {
if (graph.get(c1).add(c2)) {
                    indegree.put(c2, indegree.get(c2) + 1);
                }
break;
            }
        }
    }

    Queue<Character> queue = new LinkedList<>();
for (char c : indegree.keySet()) {
if (indegree.get(c) == 0) queue.offer(c);
    }

    StringBuilder sb = new StringBuilder();
while (!queue.isEmpty()) {
char c = queue.poll();
        sb.append(c);
for (char nei : graph.get(c)) {
            indegree.put(nei, indegree.get(nei) - 1);
if (indegree.get(nei) == 0) queue.offer(nei);
        }
    }

return sb.length() == indegree.size() ? sb.toString() : "";
}

这段代码咋样,看着是不是不太难?但里面暗藏几个坑,很多人第一次做时都会被搞晕。

第一个大坑是那个w1.startsWith(w2)判断,很多人忽略了这个特殊情况。比如输入 ["abc", "ab"],你会本能地认为“a在b前”,但其实这是非法字典顺序,按人话说就是“短词排在长词后面但包含前者”不合理,直接返回空。

第二个是graph.get(c1).add(c2)这一行:只有在第一次插入边的时候才需要更新入度!有的同学一激动,每次都+1,这就...挂了 🙃。

整个算法用的就是标准的Kahn拓扑排序模板,不过结合字母的先后顺序,看起来就有点“高级感”了。

顺带一提,这种题其实还能反映你对图的基本操作熟不熟。Map当邻接表、入度统计、队列BFS……面试官看的是你思维清不清晰,代码是不是干净有逻辑,不是你会不会背模板🤨。

还有人问:为啥不是DFS做?可以,但用DFS你得加一堆标志处理环检测(0未访问,1访问中,2访问完成),虽然也能做出同样结果,但代码维护性略低,面试时间紧张我一般不推荐。

不过我最服的一类bug是啥?某些同学直接把所有单词里出现的字母按顺序拼接返回 🤯,纯属“拍脑袋输出”,连个拓扑味都没有。火星人估计看了都得骂:你搁这整段落排序呢?

最后留个脑洞问题:这个题其实可以延展到多语言词典构建、多领域本体抽象,甚至图神经网络的输入建图逻辑。一个“火星词典”能衍生出不少东西,感兴趣的可以自己深挖一下👀

最后,我为大家打造了一份deepseek的入门到精通教程,完全免费:https://www.songshuhezi.com/deepseek

也可以看我写的这篇文章《DeepSeek满血复活,直接起飞!》来进行本地搭建。

-END-

ok,今天先说到这,老规矩,给大家分享一份不错的副业资料,感兴趣的同学可以链接我,微信:hls404 找我领取。

以上,就是今天的分享了,看完文章记得右下角点赞,也欢迎在评论区写下你的留言。