[LeetCode] 886. Possible Bipartition

Given a set of N people (numbered 1, 2, ..., N), we would like to split everyone into two groups of any size.

Each person may dislike some other people, and they should not go into the same group. 

Formally, if dislikes[i] = [a, b], it means it is not allowed to put the people numbered a and b into the same group.

Return true if and only if it is possible to split everyone into two groups in this way.

Example 1:

Input: N = 4, dislikes = [[1,2],[1,3],[2,4]]
Output: true
Explanation: group1 [1,4], group2 [2,3]

Example 2:

Input: N = 3, dislikes = [[1,2],[1,3],[2,3]]
Output: false

Example 3:

Input: N = 5, dislikes = [[1,2],[2,3],[3,4],[4,5],[1,5]]
Output: false

Note:

  1. 1 <= N <= 2000
  2. 0 <= dislikes.length <= 10000
  3. 1 <= dislikes[i][j] <= N
  4. dislikes[i][0] < dislikes[i][1]
  5. There does not exist i != j for which dislikes[i] == dislikes[j].

可能的二分法。题意是给一个数字N代表有N个人,还有一个二维数组dislikes,代表每两个人之间的dislike关系。请返回是否有可能将N个人分成两组。

这个题实际是在考能否将一个图的节点分成两组。有几种不同的思路,我这里给出DFS的思路。首先创建一个长度为N的额外数组,记录每个节点的涂色状况。我这里是把两组人一组设置成0,一组设置成1,初始化的时候所有人都是-1。再来是通过dislikes里面的关系,将input构建成一个图,我这里是用一个邻接表记录的。

开始遍历input,如果当前这个人是-1的话,则开始dfs遍历。dfs遍历的时候去检查,如果当前这个人dislike的另一个人(也就是当前这个人的邻居)已经被染成同一种颜色,则return false;同时,如果当前的人的邻居没有被染色但是当这个邻居的邻居之间有同色的情形,也return false。

时间O(V + E)

空间O(n^2) - 记录了graph

Java实现

 1 class Solution {
 2     public boolean possibleBipartition(int N, int[][] dislikes) {
 3         // corner case
 4         if (dislikes == null || dislikes.length == 0) {
 5             return true;
 6         }
 7 
 8         // normal case
 9         List<List<Integer>> graph = buildGraph(N, dislikes);
10         // 开一个数组表示每个顶点的颜色。-1表示未访问,0和1分别表示两种颜色
11         int[] colors = new int[N];
12         Arrays.fill(colors, -1);
13         for (int i = 0; i < N; i++) {
14             if (colors[i] == -1) {
15                 if (!dfs(i, graph, colors, 0)) {
16                     return false;
17                 }
18             }
19         }
20         return true;
21     }
22 
23     // 从cur开始做DFS,并将cur染色为color
24     private boolean dfs(int cur, List<List<Integer>> graph, int[] colors, int color) {
25         colors[cur] = color;
26         for (int next : graph.get(cur)) {
27             // 如果发现某个邻居的颜色和自己一样,则返回false
28             if (colors[next] == color) {
29                 return false;
30             }
31             // 若发现next遍历后会发现某两个邻居染色一样,也返回false
32             if (colors[next] == -1 && !dfs(next, graph, colors, color ^ 1)) {
33                 return false;
34             }
35         }
36         return true;
37     }
38 
39     private List<List<Integer>> buildGraph(int N, int[][] dislikes) {
40         List<List<Integer>> graph = new ArrayList<>(N);
41         for (int i = 0; i < N; i++) {
42             graph.add(new ArrayList<>());
43         }
44         for (int[] dislike : dislikes) {
45             graph.get(dislike[0] - 1).add(dislike[1] - 1);
46             graph.get(dislike[1] - 1).add(dislike[0] - 1);
47         }
48         return graph;
49     }
50 }

LeetCode 题目总结

猜你喜欢

转载自www.cnblogs.com/cnoodle/p/12977970.html
今日推荐