[LeetCode] 886. Possible Bipartition

We want to split a group of n people (labeled from 1 to n) into two groups of any size. Each person may dislike some other people, and they should not go into the same group.

Given the integer n and the array dislikes where dislikes[i] = [ai, bi] indicates that the person labeled ai does not like the person labeled bi, return true 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: The first group has [1,4], and the second group has [2,3].

Example 2:
Input: n = 3, dislikes = [[1,2],[1,3],[2,3]]
Output: false
Explanation: We need at least 3 groups to divide them. We cannot put them in two groups.

Constraints:
1 <= n <= 2000
0 <= dislikes.length <= 104
dislikes[i].length == 2
1 <= ai < bi <= n
All the pairs of dislikes are unique.

可能的二分法。

给定一组 n 人(编号为 1, 2, ..., n), 我们想把每个人分进任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。

给定整数 n 和数组 dislikes ,其中 dislikes[i] = [ai, bi] ,表示不允许将编号为 ai 和 bi的人归入同一组。当可以用这种方法将所有人分进两组时,返回 true;否则返回 false。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/possible-bipartition
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

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

这个题实际是在考能否将一个图的所有节点分成两组。思路还是染色法,类似 785 题。

复杂度

时间O(V + E) - V是节点数,E是边数
空间O(n)

代码

BFS 实现

class Solution {
    public boolean possibleBipartition(int n, int[][] dislikes) {
        List<List<Integer>> g = new ArrayList<>();
        for (int i = 0; i <= n; i++) {
            g.add(new ArrayList<>());
        }

        for (int[] d : dislikes) {
            g.get(d[0]).add(d[1]);
            g.get(d[1]).add(d[0]);
        }

        int[] colors = new int[n + 1];
        for (int i = 0; i <= n; i++) {
            if (colors[i] != 0) {
                continue;
            }
            Queue<Integer> queue = new LinkedList<>();
            queue.offer(i);
            colors[i] = 1;
            while (!queue.isEmpty()) {
                int cur = queue.poll();
                for (int nei : g.get(cur)) {
                    if (colors[nei] == 0) {
                        colors[nei] = -colors[cur];
                        queue.offer(nei);
                    } else if (colors[nei] == colors[cur]) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
}

DFS 实现

class Solution {
    public boolean possibleBipartition(int n, int[][] dislikes) {
        // corner case
        if (dislikes == null || dislikes.length == 0) {
            return true;
        }

        // normal case
        List<List<Integer>> graph = new ArrayList<>();
        buildGraph(n, dislikes, graph);
        int[] colors = new int[n + 1];
        for (int i = 0; i < n; i++) {
            if (colors[i] == 0 && !dfs(i, graph, colors, 1)) {
                return false;
            }
        }
        return true;
    }

    private void buildGraph(int n, int[][] dislikes, List<List<Integer>> graph) {
        for (int i = 0; i <= n; i++) {
            graph.add(new ArrayList<>());
        }
        for (int[] d : dislikes) {
            graph.get(d[0]).add(d[1]);
            graph.get(d[1]).add(d[0]);
        }
    }

    private boolean dfs(int cur, List<List<Integer>> graph, int[] colors, int color) {
        colors[cur] = color;
        for (int next : graph.get(cur)) {
            // 如果发现某个邻居的颜色和自己一样,则返回false
            if (colors[next] == color) {
                return false;
            }
            // 若发现next遍历后会发现某两个邻居染色一样,也返回false
            if (colors[next] == 0 && !dfs(next, graph, colors, -color)) {
                return false;
            }
        }
        return true;
    }
}

相关题目

785. Is Graph Bipartite
886. Possible Bipartition
1129. Shortest Path with Alternating Colors
posted @ 2020-05-28 04:45  CNoodle  阅读(138)  评论(0)    收藏  举报