ShardingSphere-Proxy核心功能与部署实践指南
2026/7/22 2:17:06
写在前面:最近刷 LeetCode 遇到一道题(2092. Find All People With Secret),题目要求模拟“秘密”在专家之间的传播过程。我一开始想到用
set+ BFS,后来又看到有人用并查集(Union-Find)解法。于是我就开始思考:这两种方法到底有什么区别?能不能互相替代?哪种更高效?这篇笔记就是我对这个问题的探索和总结,希望能帮到未来的自己,也欢迎你一起学习!
题目大意:
n个专家(编号 0 到 n-1)。firstPerson。[x, y, time]),如果其中一人知道秘密,另一人立刻也知道。关键点:按时间分组处理,每组内做连通性传播。
set+ BFSset(比如叫known)记录当前知道秘密的人。known中已知的人出发,BFS 遍历整个连通分量。known。known={0,firstPerson}meetings.sort(key=lambdax:x[2])i=0whilei<len(meetings):# 收集同一时间的所有会议,建图graph=defaultdict(list)while同一时间:x,y=meeting graph[x].append(y)graph[y].append(x)i+=1# BFS:从 known 中已在图里的人出发queue=deque([pforpingraphifpinknown])visited=set(queue)whilequeue:cur=queue.popleft()fornbingraph[cur]:ifnbnotinvisited:visited.add(nb)queue.append(nb)known|=visited# 合并新知道秘密的人known中的人。known。# 每个时间点新建 parent 字典parent={p:pforpinpeople_in_this_time}deffind(x):ifparent[x]!=x:parent[x]=find(parent[x])returnparent[x]forx,yinmeetings_at_this_time:union(x,y)# 分组groups=defaultdict(set)forpinpeople_in_this_time:groups[find(p)].add(p)# 检查哪些 group 有 known 的人forgroupingroups.values():ifany(pinknownforpingroup):known|=group| 维度 | Set + BFS/DFS | 并查集(Union-Find) |
|---|---|---|
| 适用场景 | 离线、分批、需状态传播 | 在线动态连通性、仅需判断连通 |
| 时间复杂度 | O(M log M + M) | O(M log M + M α(N)) |
| 常数开销 | 较小(只遍历相关部分) | 稍大(需初始化、分组) |
| 剪枝能力 | ✅ 强(从已知出发) | ❌ 弱(必须处理所有节点) |
| 代码难度 | 简单直观 | 易错(UF 隔离问题) |
| 能否获取路径 | ✅ 可以 | ❌ 不行 |
| 在线查询支持 | ❌ 不支持 | ✅ 支持 |
💡结论:
对于本题这类“分阶段、状态传播”的问题,Set + BFS 更合适。
但对于“边动态加入、频繁查询连通性”的问题(如 Kruskal 最小生成树),并查集不可替代。
答案是:不能。
例如:LeetCode 2092、朋友圈、岛屿数量等。
并查集≈ “户口本管理员”
→ 你问:“A 和 B 是一家人吗?”
→ 他秒查户口本告诉你“是”或“不是”,但不知道家里谁做饭、谁带娃。
BFS/DFS + set≈ “社区社工上门走访”
→ 你让他从 A 家出发,看看能串门到哪些人家。
→ 他不仅能告诉你连通性,还能记录路径、传播消息、收集需求。
所以:任务不同,工具不同。