程序员老鬼

程序员老公摆烂,彻底废了,被优化后三个月没找到工作,最后跑去送快递了,原本一个月两万现在才四五千,不知道他怎么能干下去的!

刚看到个贴子,说一姑娘吐槽程序员老公被裁三个月找不到工作,现在去送快递,一个月四五千,她觉得人彻底废了,动了离婚的心。

Image

网友们的回复我看了看,有骂男的摆烂不进步的,也有说女方现实、嫌贫爱富的。怎么说呢,我觉得这事不能只盯着工资看,也不能替任何一方洗白。

从我的角度看,被优化后确实难,但难不等于躺平。老公如果真是每天打游戏不学习,那问题不是送快递,而是没规划没担当;妻子一边嫌弃一边又不谈未来,只把“离婚”挂嘴边,也是在逃避。

婚姻不是岗位外包,收入有起伏很正常,关键看两个人有没有一起扛事的劲儿。说到底,一边努力自救,一边互相扶一把,比互相指责有用多了。

面试题:判断二分图

昨天晚上十一点多吧,我在公司楼下抽烟(其实是被线上报警薅出来的),我们组小李突然在群里丢了个题:判断二分图。我当时脑子一抽就说,这玩意跟“把人分两拨坐两边别打起来”一样,你给我一堆关系边,能不能做到:每条边两端必须坐在不同拨。做不到的情况呢,基本就是出现了“奇数环”,比如 1-2-3-1 这种,怎么分都得有一条边同侧,尴尬死。

然后我就想到前两天排查一个链路,服务 A 调 B 调 C,最后绕回 A(别笑,真见过),环一出来,定位都费劲。图论这块也是同理,你只要沿着边一层一层扩散,给节点“染色”,相邻必须异色。染着染着发现某条边两头颜色一样,那就寄了,说明出现矛盾,也就是二分图不成立。

对了这里有个小坑,很多人默认图是连通的,其实题目一般不保证。像我们线上那种“部分客户走老流程、部分客户走新流程”,图也会断成几坨。所以得从每个没染过色的点都启动一次 BFS/DFS,不然漏了。

我习惯用 BFS,原因很朴素:队列稳,debug 好看,日志也好打(我现在对日志有阴影…)。颜色数组用 0/1/-1 三态,0 表示没访问过,1 和 -1 表示两边。边用邻接表,别用矩阵,矩阵在大点数据下就跟把 JVM 堆当垃圾桶一样,迟早炸。

Java 代码我直接贴一份我平时会写的风格,能跑,别嫌啰嗦哈:

import java.util.*;

/**
 * 判断无向图是否为二分图
 * n: 点编号假设是 0..n-1
 * edges: 每条边 edges[i] = [u, v]
 */

publicclassBipartiteCheck{

publicstaticbooleanisBipartite(int n, int[][] edges){
        List<Integer>[] g = new ArrayList[n];
for (int i = 0; i < n; i++) g[i] = new ArrayList<>();

// 构图:无向图双向加边
for (int[] e : edges) {
int u = e[0], v = e[1];
            g[u].add(v);
            g[v].add(u);
        }

int[] color = newint[n]; // 0 未染色, 1 和 -1 为两种颜色
        ArrayDeque<Integer> q = new ArrayDeque<>();

for (int i = 0; i < n; i++) {
if (color[i] != 0) continue;

// 这个连通块从 i 开始染色
            color[i] = 1;
            q.add(i);

while (!q.isEmpty()) {
int cur = q.poll();
for (int nxt : g[cur]) {
if (color[nxt] == 0) {
                        color[nxt] = -color[cur];
                        q.add(nxt);
                    } elseif (color[nxt] == color[cur]) {
// 相邻同色,出现矛盾 => 不是二分图
returnfalse;
                    }
                }
            }
        }
returntrue;
    }

// 随手跑个例子
publicstaticvoidmain(String[] args){
int n1 = 4;
int[][] e1 = {{0,1},{1,2},{2,3}};           // 链式,true
int n2 = 3;
int[][] e2 = {{0,1},{1,2},{2,0}};           // 三角形,false

        System.out.println(isBipartite(n1, e1));
        System.out.println(isBipartite(n2, e2));
    }
}

你看它逻辑就跟我刚说的“分两拨坐两边”一样:起点先随便放左边(color=1),它的邻居必须放右边(-1),再往外扩散。扩散过程中只要发现“你俩明明有关系却被我分到同一边”,立刻返回 false,别硬撑,硬撑就像线上故障你假装没看见一样,最后锅更大。

复杂度也挺舒服,邻接表下就是 O(n + m)(点+边),空间也是 O(n + m)。要我说这题最大的价值不是面试那点分数,是你以后做权限系统、分组、AB 实验隔离、甚至服务依赖图,都能用这个思路快速判断“这坨关系能不能干净地切两边”,不然一团乱麻你还以为是自己日志没打全…行了我先不说了,刚又有人在群里@我说生产环境慢查询,哎。

-END-