十几个人的小公司,老板突然来一句:谁能牵头结合咱们公司业务,开发一款编程语言?
兄弟们,刚刚看到一个帖子,这次真的给我干沉默了。
十几个人的小公司,老板突然在群里扔下一句:“谁能牵头结合咱们公司业务,开发一款编程语言?”……这不是在开玩笑嘛?😅
说实话,我之前待的公司也遇到过类似的事,老板看大厂都在搞AI,头脑一热就立马下了任务:“我们也整一个AI系统,用来优化流程。”结果,搞了两个月,AI还没出来,人先优化离职了三四个……
说实话吧,十几个人的小公司,能不欠工资就已经是超神发挥了,老板们千万别一边发不出年终奖,一边想着搞出“XXLang”。
不过转念一想,老板这行为也能理解……毕竟这年头,小公司活着都难,有时候不瞎折腾一下,好像都没安全感。
只是拜托了,下次折腾之前,能不能先考虑一下——服务器有吗?人手够吗?饭都吃不饱呢,就别想着造火箭了。【备注:文末可领最新资料】
算法题:有向图中最大颜色值
局长
今天我们来看一道非常由意思的算法题,这个题一上来其实不难理解:我们给一个有向图,每个节点有个颜色标记,要求找到从某一条路径上能得到的“颜色值”的最大值。颜色值怎么定义?同一路径上最多的那个颜色出现次数。
听上去有点像是要数颜色频次?对,但加上“路径”,就意味着我们得在图里找最长路径上颜色最多的情况,这就不是普通的遍历能搞定的了。
说白了这题是一个拓扑排序 + 动态规划的组合技。
一开始看到题目的时候我还在想:这题不就是DFS?搞个hashmap记录路径中颜色数量就完了。后来试了一下就意识到自己天真了。图里可能有环!有环还怎么统计路径?直接GG。
所以我们第一步得干嘛?判环。
拓扑排序是图论里处理有向图最常见的套路之一,它的本质其实是个BFS(也有DFS写法,但我还是偏爱BFS,写起来顺点)。
我们先统计每个节点的入度,然后把入度为0的点丢进队列里,一边遍历一边更新每个节点颜色的最大频次。
这里是关键:我们不仅要判断有没有环,还要对每个颜色统计在所有路径中从起点到当前节点的最大频次。也就是说,对每个节点,都维护一个长度为26的数组(因为颜色是'a'到'z'),来记录每种颜色出现的最大次数。
来个关键代码片段,感受下:
int[][] count = newint[n][26]; // 每个节点的颜色统计
Queue<Integer> queue = new LinkedList<>();
int[] indegree = newint[n]; // 入度统计
// 构建图和入度
for (int[] edge : edges) {
graph.get(edge[0]).add(edge[1]);
indegree[edge[1]]++;
}
// 入度为0的点进队列
for (int i = 0; i < n; i++) {
if (indegree[i] == 0) {
queue.offer(i);
count[i][colors.charAt(i) - 'a'] = 1;
}
}
int visited = 0, res = 0;
while (!queue.isEmpty()) {
int node = queue.poll();
visited++;
for (int nei : graph.get(node)) {
for (int i = 0; i < 26; i++) {
count[nei][i] = Math.max(count[nei][i], count[node][i] + (i == colors.charAt(nei) - 'a' ? 1 : 0));
}
if (--indegree[nei] == 0) queue.offer(nei);
}
res = Math.max(res, Arrays.stream(count[node]).max().getAsInt());
}
// 如果没遍历完所有点,说明有环
return visited == n ? res : -1;
注意这里一个点:如果图里有环,肯定有节点入度永远不为0,那就永远进不了队列,也就是说最后visited的节点数肯定小于n。所以只要判断这一点,就能确定图里有没有环,免得又多搞一个DFS判环,省事。
我一开始写这个题时还真栽在了"路径统计"上,想当然地以为可以在DFS路径里传一个Map,最后取最大值……结果性能爆炸,还TLE🤯。
换这个做法之后,性能嘎嘎稳。
说实话这题不是特别难,但它把几个点结合得挺巧的:拓扑排序是防止环+建立路径序的,动态规划是用来记录路径中颜色的最大值。这种组合题,在面试里出现概率很高,因为它能测出你图论和DP的基本功,而且代码也不少,正好卡你个写代码的时间。
最后补一嘴:如果用DFS也不是不能做,但你得加缓存(记忆化搜索)+环检测+颜色统计,一不小心细节出错就是爆栈+重复计算双杀,写起来不如拓扑来的直接。
你要说这题面试要问我,我可能会反问面试官一句:“要不我们手撕个拓扑+颜色统计?”😏
这个题练完之后,推荐去刷下Course Schedule II那题,理解拓扑排序是怎么搞的,那个题也能当环检测模板用,蛮经典的。
对了,有个哥们问我:“Java能不能不用二维数组存颜色统计?太大了!” 其实是可以优化空间的,比如只存最近更新的颜色值,但那得看面试官让不让你发挥了。标准写法稳妥第一。🫡
那你们再想想,如果图的节点有上百万个,这个做法还能撑得住吗?欢迎讨论~
最后,我为大家打造了一份deepseek的入门到精通教程,完全免费:https://www.songshuhezi.com/deepseek
也可以看我写的这篇文章《DeepSeek满血复活,直接起飞!》来进行本地搭建。
-END-
以上,就是今天的分享了,看完文章记得右下角点赞,也欢迎在评论区写下你的留言。