Python技术迷

某大厂员工:有个很菜的同事,去了体制内像他这样有学历没技术的,去体制内,是最不浪费个人优势的,能完美避开自己的短处!

某大厂员工:有个很菜的同事,去了体制内像他这样有学历没技术的,去体制内,是最不浪费个人优势的,能完美避开自己的短处!

你说他不努力吧,好像也不是;你说他强吧,项目一压上来就露馅。

Image

结果人家转头去了体制内,反而像换了个地图。学历能用上,背景能解释得通,表达能力也算加分,关键是不用天天跟 bug、性能、上线窗口硬刚。短板一下被藏起来,长处还被放大了。

所以有时候不是人菜,是赛道选得太折磨。放错地方叫混子,放对地方可能还挺稳。职场这玩意儿,真不是只看能力,还看你会不会挑坑。


算法题:省份数量

isConnected[i][i] 全是 1,这玩意儿别拿来当有效连接算。

省份数量这题,真正要数的不是城市数量,也不是矩阵里有多少个 1,而是有多少坨互相能连到一起的城市。

比如 A 和 B 连,B 和 C 连,那 A、B、C 就算一个省。哪怕 A 和 C 在矩阵里不是直接相连,也不能拆成两个。

这个地方我一般不用 DFS 写,虽然也能过。矩阵题用并查集更顺手,尤其是看到“传递关系”这几个字,基本就该往合并集合上想了。

矩阵大概长这样:

int[][] isConnected = {
    {1, 1, 0},
    {1, 1, 0},
    {0, 0, 1}
};

0 号城市和 1 号城市连着,2 号城市自己一坨,所以答案是 2。

代码别写复杂,关键就三件事:初始化每个城市自己是一个省;看到两个城市相连就合并;最后数根节点。

classSolution{
publicintfindCircleNum(int[][] isConnected){
int n = isConnected.length;
        ProvinceSet set = new ProvinceSet(n);

for (int from = 0; from < n; from++) {
for (int to = from + 1; to < n; to++) {
if (isConnected[from][to] == 1) {
                    set.merge(from, to);
                }
            }
        }

return set.count();
    }

staticclassProvinceSet{
privatefinalint[] parent;
privatefinalint[] size;
privateint groups;

        ProvinceSet(int n) {
            parent = newint[n];
            size = newint[n];
            groups = n;

for (int i = 0; i < n; i++) {
                parent[i] = i;
                size[i] = 1;
            }
        }

introot(int city){
while (city != parent[city]) {
                parent[city] = parent[parent[city]];
                city = parent[city];
            }
return city;
        }

voidmerge(int a, int b){
int ra = root(a);
int rb = root(b);

if (ra == rb) {
return;
            }

if (size[ra] < size[rb]) {
                parent[ra] = rb;
                size[rb] += size[ra];
            } else {
                parent[rb] = ra;
                size[ra] += size[rb];
            }

            groups--;
        }

intcount(){
return groups;
        }
    }
}

这里有个细节,内层循环从 from + 1 开始。

因为这个矩阵是对称的:

isConnected[0][1] == isConnected[1][0]

扫两遍没意义。isConnected[i][i] 又永远是自己连自己,也不用看。

这题最容易写偏的地方,是把“直接相连”当成“一个省”。比如:

0 - 1
1 - 2

0 和 2 没有直接连线,但它们通过 1 连上了,所以还是一个省。

并查集处理这种传递关系比较稳,merge(0,1) 后,0 和 1 是一组;再 merge(1,2),2 也被并进来。最后剩几个集合,就有几个省。

复杂度也很直观,矩阵必须扫一遍上三角,所以时间主要是 O(n²)。并查集的查找和合并因为做了路径压缩,基本可以当成很小的常数看。

这题不难,但它很适合拿来判断一个人是不是只会套 DFS。看到“连通块”,脑子里至少要同时有 DFS、BFS、并查集三种解法。矩阵给得这么直接,并查集写起来反而最干净。