程序员老鬼

领导让我脱离ai写代码,我纯手工写了,领导说我拉了一坨大的。。

刚看到个贴子,说一个程序员被领导要求“脱离AI手写代码”,结果他真的纯手工写了,领导看完骂他“拉了一坨大的”。这贴子一出,网友炸了,有的说领导自相矛盾,有的说这哥们太老实。

Image

我觉得这事吧,本质不是AI和人工的对立,而是“成果导向”的问题。领导要你脱离AI,可能是想看你有没有独立思考能力,不是真的要你拒绝工具。结果你真“手写”了,他反而觉得你不懂效率。听着荒唐,其实很典型——职场上很多任务都是“揣摩上意”的考题。

网友们骂领导双标也有道理,但反过来想,咱打工人也得懂规则:用不用AI不是重点,能不能写出好代码、解决问题才是底线。说到底,工具只是刀,关键还得看谁拿着。【备注:文末可领最新资料】

算法题:单词游戏

想象一下你和同桌在玩一个小游戏: 桌上有一堆英文单词,全是小写,比如:ab、bc、cd、da。

规则是这样的: 前一个单词的最后一个字母,要等于下一个单词的第一个字母,而且——

  • 每个单词必须用一次、只能用一次
  • 最后一个单词的结尾字母,还得能接回第一个单词的开头字母,形成一个环

问题就变成了: 给你 N 个单词,能不能把它们排成这样一个圈? 这就是经典的“单词游戏”算法题。

怎么抽象成图论问题?

这种题如果直接在字符串上硬拼,基本会被绕晕。换个角度想,会简单很多。

我们可以把 每个字母 看成一个点(顶点),一共 26 个:a ~ z。 然后把 每个单词 看成一条从「首字母」到「尾字母」的有向边。

举个例子:

  • 单词 ab:就是从 a 指向 b 的一条边
  • 单词 bc:就是从 b 指向 c 的一条边

这样一来,题目就变成一句很“图论”的话:

给定一张有向图,每条边表示一个单词,能不能用所有边恰好走一遍,并且走成一个回路?

这在图论里有一个专门的名字:有向图的欧拉回路(Eulerian Circuit)。

欧拉回路的两个关键条件

对于一张有向图,要想存在包含所有边的欧拉回路,需要满足两个核心条件:

  1. 每个点的入度 = 出度

  • 出度:以这个点为起点的边的条数
  • 入度:以这个点为终点的边的条数 对应到我们的题目,就是: 某个字母开头的单词有多少个,它结尾的单词也得有多少个,否则“接不平”。
  • 所有“出现过的点”在忽略方向后是连通的简单说就是: 把边当成无向边来看的时候,所有参与过单词的字母,必须都在同一个连通块里。 否则就会出现“两坨不相干的字母群”,那肯定不可能把所有单词串成一个圈。

  • 所以算法思路就很明确了:

    • 用 26 个点建图
    • 统计每个点的入度、出度
    • 用 DFS / BFS 检查连通性
    • 度数 & 连通性条件都满足,就能构成“单词游戏”的闭环

    具体算法步骤(用人话串一遍)

    大概流程如下:

    1. 准备几个数组:

    • in[26]:记录每个字母的入度
    • out[26]:记录每个字母的出度
    • adj:无向邻接表,用来做连通性检查(把有向边当成无向边加入)
  • 遍历每个单词 w:

    • u = w.charAt(0) - 'a' 作为起点
    • v = w.charAt(w.length()-1) - 'a' 作为终点
    • out[u]++,in[v]++
    • 在无向图里加边:u <-> v
  • 检查入度和出度:

    • 对于每个字母 i:如果 in[i] != out[i],那就直接判定 不可能成环
  • 检查连通性:

    • 找一个“度数 > 0” 的起点 start
    • 从 start 做一次 DFS / BFS(用无向图)
    • 把所有“度数 > 0 的点”都数一下,看是否都被访问到了
    • 如果有某个参与过单词的字母没有被访问到,也是不行的
  • 如果以上两个检查都通过,那么答案就是:可以完成这个单词游戏。

  • 下面给一份相对简洁的 Java 写法,核心就是上面那套逻辑:

    import java.util.*;

    publicclassWordGame{

    // 判断是否能把所有单词排成一个首尾相接的圈
    publicstaticbooleancanFormCircle(List<String> words){
    int[] in = newint[26];
    int[] out = newint[26];
            List<Integer>[] adj = new ArrayList[26];
    for (int i = 0; i < 26; i++) {
                adj[i] = new ArrayList<>();
            }

    // 记录哪些字母真正出现过
    boolean[] used = newboolean[26];

    for (String w : words) {
    if (w == null || w.length() == 0) continue;
    char first = w.charAt(0);
    char last = w.charAt(w.length() - 1);
    int u = first - 'a';
    int v = last - 'a';

                out[u]++;
                in[v]++;
                used[u] = used[v] = true;

    // 无向图,用于连通性检查
                adj[u].add(v);
                adj[v].add(u);
            }

    // 条件一:入度 = 出度
    for (int i = 0; i < 26; i++) {
    if (in[i] != out[i]) {
    returnfalse;
                }
            }

    // 找一个度数 > 0 的点作为 DFS 起点
    int start = -1;
    for (int i = 0; i < 26; i++) {
    if (in[i] + out[i] > 0) {
                    start = i;
    break;
                }
            }
    // 没有任何单词,其实可以认为既成环又没意义,这里按“无法形成”处理
    if (start == -1) returnfalse;

    // 条件二:忽略方向后,所有出现过的点必须连通
    boolean[] visited = newboolean[26];
            dfs(start, adj, visited);

    for (int i = 0; i < 26; i++) {
    if (used[i] && !visited[i]) {
    returnfalse;
                }
            }

    returntrue;
        }

    privatestaticvoiddfs(int u, List<Integer>[] adj, boolean[] visited){
            visited[u] = true;
    for (int v : adj[u]) {
    if (!visited[v]) {
                    dfs(v, adj, visited);
                }
            }
        }

    // 随便写个 main 简单测一下
    publicstaticvoidmain(String[] args){
            List<String> words1 = Arrays.asList("ab", "bc", "cd", "da");
            System.out.println(canFormCircle(words1)); // true

            List<String> words2 = Arrays.asList("ab", "bc", "ca", "ad");
            System.out.println(canFormCircle(words2)); // false
        }
    }

    你在刷题平台上做这道“单词游戏”的题时,大多数输入输出格式都会不太一样(有的多组用例,有的是从标准输入读),但核心判断逻辑基本就是这套:欧拉回路 = 入度出度相等 + 连通性 OK。

    剩下的,就是把这坨逻辑根据题目的输入格式,稍微包一包就能 AC 了。

    -END-

    我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

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