【LeetCode每日一题】——LCR 106.判断二分图
文章目录
- 一【题目类别】
- 二【题目难度】
- 三【题目编号】
- 四【题目描述】
- 五【题目示例】
- 六【题目提示】
- 七【题目注意】
- 八【解题思路】
- 九【时空频度】
- 十【代码实现】
- 十一【提交结果】
一【题目类别】
- 图
二【题目难度】
- 中等
三【题目编号】
- LCR 106.判断二分图
四【题目描述】
- 存在一个 无向图 ,图中有
n
个节点。其中每个节点都有一个介于0
到n - 1
之间的唯一编号。 - 给定一个二维数组
graph
,表示图,其中graph[u]
是一个节点数组,由节点u
的邻接节点组成。形式上,对于graph[u]
中的每个v
,都存在一条位于节点u
和节点v
之间的无向边。该无向图同时具有以下属性:- 不存在自环(
graph[u]
不包含u
)。 - 不存在平行边(
graph[u]
不包含重复值)。 - 如果
v
在graph[u]
内,那么u
也应该在graph[v]
内(该图是无向图) - 这个图可能不是连通图,也就是说两个节点
u
和v
之间可能不存在一条连通彼此的路径。
- 不存在自环(
- 二分图 定义:如果能将一个图的节点集合分割成两个独立的子集
A
和B
,并使图中的每一条边的两个节点一个来自A
集合,一个来自B
集合,就将这个图称为 二分图 。 - 如果图是二分图,返回
true
;否则,返回false
。
五【题目示例】
-
示例 1:
- 输入:graph = [[1,2,3],[0,2],[0,1,3],[0,2]]
- 输出:false
- 解释:不能将节点分割成两个独立的子集,以使每条边都连通一个子集中的一个节点与另一个子集中的一个节点。
-
示例 2:
- 输入:graph = [[1,3],[0,2],[1,3],[0,2]]
- 输出:true
- 解释:可以将节点分成两组: {0, 2} 和 {1, 3} 。
六【题目提示】
graph.length == n
1 <= n <= 100
0 <= graph[u].length < n
0 <= graph[u][i] <= n - 1
graph[u]
不会包含u
graph[u]
的所有值 互不相同- 如果
graph[u]
包含v
,那么graph[v]
也会包含u
七【题目注意】
- 本题与主站 785 题相同: https://leetcode-cn.com/problems/is-graph-bipartite/
八【解题思路】
- 广度优先搜索+染色法
- 我们做如下定义:
- 定义染色数组,长度为节点数
- 将染色数组全部初始化为-1,表示所有节点均没有染色
- 遍历所有节点(防止图非联通)
- 将起始节点染色(染色为0)
- 然后遍历其邻接节点,根据定义,其邻接节点如果需要染色则将其染成相反的颜色,若其与其邻接节点颜色相同,那么根据定义,此时的图就不是连通图
- 最后返回结果即可
- 具体细节可以参考下面的代码
九【时空频度】
- 时间复杂度: O ( m + n ) O(m + n) O(m+n), m m m为图中节点数, n n n为图中边数
- 空间复杂度: O ( m ) O(m) O(m), m m m为图中节点数
十【代码实现】
- Java语言版
class Solution {
public boolean isBipartite(int[][] graph) {
int n = graph.length;
// 初始化每个节点的颜色为 -1(未染色)
int[] color = new int[n];
for (int i = 0; i < n; i++) {
color[i] = -1;
}
for (int i = 0;i < n; i++) {
// 如果节点 i 未染色
if (color[i] == -1) {
Queue<Integer> queue = new LinkedList<>();
queue.offer(i);
// 将起始节点染成颜色 0
color[i] = 0;
while (!queue.isEmpty()) {
int node = queue.poll();
for (int neighbot : graph[node]) {
// 如果邻接节点未染色
if (color[neighbot] == -1) {
// 染成相反颜色
color[neighbot] = 1 - color[node];
queue.offer(neighbot);
// 如果邻接节点颜色相同
} else if (color[neighbot] == color[node]) {
return false;
}
}
}
}
}
return true;
}
}
- Python语言版
class Solution:
def isBipartite(self, graph: List[List[int]]) -> bool:
# 初始化每个节点的颜色为 -1(未染色)
n = len(graph)
color = [-1] * n
for i in range(n):
# 如果节点 i 未染色
if color[i] == -1:
queue = deque([i])
# 将起始节点染成颜色 0
color[i] = 0
while queue:
node = queue.popleft()
for neighbor in graph[node]:
# 如果邻接节点未染色
if color[neighbor] == -1:
# 染成相反颜色
color[neighbor] = 1 - color[node]
queue.append(neighbor)
# 如果邻接节点颜色相同
elif color[neighbor] == color[node]:
return False
return True
- C++语言版
class Solution {
public:
bool isBipartite(vector<vector<int>>& graph) {
int n = graph.size();
// 初始化每个节点的颜色为 -1(未染色)
vector<int> color(n, -1);
for (int i = 0; i < n; i++) {
// 如果节点 i 未染色
if (color[i] == -1) {
queue<int> q;
q.push(i);
// 将起始节点染成颜色 0
color[i] = 0;
while (!q.empty()) {
int node = q.front();
q.pop();
for (int neighbot : graph[node]) {
// 如果邻接节点未染色
if (color[neighbot] == -1) {
// 染成相反颜色
color[neighbot] = 1 - color[node];
q.push(neighbot);
// 如果邻接节点颜色相同
} else if (color[neighbot] == color[node]) {
return false;
}
}
}
}
}
return true;
}
};
十一【提交结果】
-
Java语言版
-
Python语言版
-
C语言版