LeetCode 785. 判断二分图
字数 1345 2025-10-27 17:41:11
LeetCode 785. 判断二分图
题目描述
给定一个无向图,包含 n 个节点(编号从 0 到 n-1)和一个边的列表。请判断这个图是否是二分图。二分图的定义是:能够将图中的所有节点分成两个独立的集合 U 和 V,使得每条边都连接 U 中的一个节点和 V 中的一个节点(即不存在连接同一集合内两个节点的边)。
示例
输入:graph = [[1,2,3],[0,2],[0,1,3],[0,2]]
输出:false
解释:无法将节点分成两个集合使得每条边都跨集合连接。例如,节点 0 与 1、2、3 相连,但 1 和 2 之间也有边,导致冲突。
解题过程
1. 核心思路
二分图的判断等价于图的二着色问题:尝试用两种颜色(例如 0 和 1)对节点进行染色,使得相邻节点颜色不同。如果能够完成染色,则是二分图;否则不是。
2. 算法选择
常用深度优先搜索(DFS)或广度优先搜索(BFS)遍历图,在遍历过程中进行染色检查:
- 初始化一个颜色数组
color[],初始值为 -1(未染色)。 - 遍历每个节点,若未染色,则从该节点开始 DFS/BFS,将其染成颜色 0,然后将其邻居染成颜色 1,邻居的邻居染成颜色 0,依此类推。
- 如果在染色过程中发现某个邻居的颜色与当前节点相同,则说明冲突,返回 false。
- 如果所有节点成功染色且无冲突,返回 true。
3. 详细步骤(以 BFS 为例)
- 步骤 1:创建颜色数组
color,长度等于节点数 n,初始值全为 -1。 - 步骤 2:遍历每个节点 i(0 到 n-1):
- 如果
color[i] == -1(未访问),将其加入队列,并染成颜色 0。 - 开始 BFS:
a. 从队列取出节点 u,检查其所有邻居 v:
b. 如果 v 未染色(color[v] == -1),将其染成与 u 相反的颜色(color[v] = 1 - color[u]),并加入队列。
c. 如果 v 已染色且color[v] == color[u],说明冲突,直接返回 false。
- 如果
- 步骤 3:若所有节点处理完毕且无冲突,返回 true。
4. 示例推导(graph = [[1,2,3],[0,2],[0,1,3],[0,2]])
- 初始化
color = [-1, -1, -1, -1]。 - 从节点 0 开始 BFS:
- 染 color[0] = 0,邻居 [1,2,3] 应染为 1。
- 处理节点 1:color[1] = 1,邻居 [0,2] 中,0 已染色且颜色不同(0≠1),合法;2 未染色,染 color[2] = 0。
- 处理节点 2:color[2] = 0,邻居 [0,1,3] 中,0 颜色不同(0=0? 冲突!因为 0 和 2 都是颜色 0,但二者有边连接),返回 false。
5. 复杂度分析
- 时间复杂度:O(n + e),其中 n 是节点数,e 是边数(每个节点和边各访问一次)。
- 空间复杂度:O(n),用于存储颜色数组和队列。
关键点
- 二分图可能不是连通图,因此需要遍历每个未访问的节点作为 BFS/DFS 的起点。
- 染色规则必须严格保证相邻节点颜色互异。