leetcode-pp / 91alg-7-daily-check

6 stars 0 forks source link

【Day 30 】2022-04-30 - 886. 可能的二分法 #33

Open azl397985856 opened 2 years ago

azl397985856 commented 2 years ago

886. 可能的二分法

入选理由

暂无

题目地址

https://leetcode-cn.com/problems/possible-bipartition/

前置知识

每个人都可能不喜欢其他人,那么他们不应该属于同一组。

形式上,如果 dislikes[i] = [a, b],表示不允许将编号为 a 和 b 的人归入同一组。

当可以用这种方法将每个人分进两组时,返回 true;否则返回 false。

 

示例 1:

输入:N = 4, dislikes = [[1,2],[1,3],[2,4]] 输出:true 解释:group1 [1,4], group2 [2,3] 示例 2:

输入:N = 3, dislikes = [[1,2],[1,3],[2,3]] 输出:false 示例 3:

输入:N = 5, dislikes = [[1,2],[2,3],[3,4],[4,5],[1,5]] 输出:false  

提示:

1 <= N <= 2000 0 <= dislikes.length <= 10000 dislikes[i].length == 2 1 <= dislikes[i][j] <= N dislikes[i][0] < dislikes[i][1] 对于dislikes[i] == dislikes[j] 不存在 i != j

duantao74520 commented 2 years ago

考察点:

图 dfs 染色

思路:

  1. 构建邻接表
  2. DFS尝试给当前节点染色:
    1. 如果当前节点没有染色,就初始化为想要染色的值
    2. 遍历所有的对头
      1. 如果对头已经染色了,并且不在我一个队列中,返回false
      2. 如果对头没有染色,就尝试用DFS染色成当前值的反颜色

代码:

class Solution {
    //染色 dfs

public:
    bool possibleBipartition(int n, vector<vector<int>>& dislikes) {
        // 构建邻接矩阵
        dp = vector<vector<int>>(n);
        for (vector<int>& dislike : dislikes) {
            dp[dislike[0]-1].emplace_back( dislike[1] -1);
            dp[dislike[1]-1].emplace_back( dislike[0] -1);
        }
        // 初始化颜色表
        color = vector<int>(n, 0); // 0 未染色, 1 染成红色  -1染成绿色
        for (int i = 0; i < n; i++) {
            if (color[i] == 0 && !dfs(i, 1)) {
                return false;
            }
        }
        return true;

    }
    // 尝试给i染成color
    bool dfs(int cur, int c) {
        color[cur] = c;
        // 遍历所有的死对头
        for (int fighter : dp[cur]) {
            // 死对头已经分配了, 并且等于我的队列
            if (color[fighter] == c) {
                return false;
            }
            // 尝试给死对头分配我的另一个队列
            if (color[fighter] == 0 && !dfs(fighter, -c)) {
                return false;
            }
        }
        return true;
    }
    private:
    vector<int> color;
    vector<vector<int>> dp;
};

复杂度:

空间:O(N2)

时间: O(N)

Yongxi-Zhou commented 2 years ago

思路

二分图,用visited标记当前染色情况,0 1 -1,对每个节点都进行BFS(不一定说连通图),如果下个要求的颜色和下个节点的颜色冲突,就返回False

代码

    class Solution(object):
        def possibleBipartition(self, n, dislikes):
            """
            :type n: int
            :type dislikes: List[List[int]]
            :rtype: bool
            """
            graph = collections.defaultdict(list)
            for d in dislikes:
                graph[d[0]].append(d[1])
                graph[d[1]].append(d[0])

            visited = [0 for i in range(n + 1)]

            for i in range(n + 1):
                if visited[i] != 0:
                    continue
                q = deque()
                q.append(i)
                visited[i] = 1
                while q:
                    cur = q.popleft()
                    curLabel = visited[cur]
                    nextLabel = -1 * curLabel
                    for nextNode in graph[cur]:
        #                 not colored
                        if visited[nextNode] == 0:
                            visited[nextNode] = nextLabel
                            q.append(nextNode)
                        elif visited[nextNode] != nextLabel:
                            return False
            # print(visited)
            return True

复杂度

time O(V + E) space O(V)

xixiao51 commented 2 years ago

Idea

Graph, DFS, node coloring Person <-> Node P1 and P2 dislike each other <-> Node 1 and Node 2 share one edge, and they can be drawed with different two colors. Other people can not be colored with two different colors.

Code

class Solution {
    List<Integer>[] graph;
    int[] color;

    public boolean possibleBipartition(int n, int[][] dislikes) {
        graph = new ArrayList[n + 1];
        color = new int[n + 1];
        for(int i = 1; i <= n; i++) {
            graph[i] = new ArrayList<Integer>();
        }

        for(int[] dislike: dislikes) {
            graph[dislike[0]].add(dislike[1]);
            graph[dislike[1]].add(dislike[0]);
        }

        for(int i = 1; i <= n; i++) {
            if(color[i] == 0 && !dfs(1, i)) {
                return false;
            }
        }
        return true;
    }

    private boolean dfs(int c, int node) {
        if(color[node] != 0) {
            return color[node] == c;
        }
        color[node] = c;
        for(int n: graph[node]) {
            if(!dfs(-c, n)) {
                return false;
            }
        }
        return true;
    }
}

Complexity Analysis

ShawYuan97 commented 2 years ago

思路

  1. 使用邻接矩阵来保存无向图
  2. 使用colors数组来表示分组情况

关键点

Python3 Code:


class Solution:
    def dfs(self, graph, colors, i, color, n):
        colors[i] = color
        for j in range(n):
            # 如果i j相互不喜欢
            if graph[i][j] == 1:
                # 相互不喜欢 不能使用同种颜色
                if colors[j] == color:
                    return False

                # 如果j还没有分配组 给他分配合适的组
                if colors[j] == 0 and not self.dfs(graph, colors, j, -1*color, n):
                    return False
        # 当前分配位置正确 可以分配
        return True

    def possibleBipartition(self, n: int, dislikes: List[List[int]]) -> bool:
        """
        将人分成两个组
        """
        # 使用邻接矩阵来表示图 1表示不喜欢 0表示没有不喜欢
        graph = [[0]*n for _ in range(n)]
        colors = [0] * n

        for a,b in dislikes:
            graph[a-1][b-1] = 1
            graph[b-1][a-1] = 1

        for i in range(n):
            if colors[i] == 0 and not self.dfs(graph, colors, i, 1, n):
                return False 
        return True

复杂度分析

令 V 为图的节点个数,E为边的个数。

zhiyuanpeng commented 2 years ago
class Solution:
    def dfs(self, g, i, c, colors):
        colors[i] = c
        # for it's connector v, try to color -1*c
        for j in g[i]:
            if colors[j] == c:
                return False
            elif colors[j] == 0 and not self.dfs(g, j, -1*c, colors):
                return False
        return True

    def possibleBipartition(self, n: int, dislikes: List[List[int]]) -> bool:
        g = collections.defaultdict(list)
        for x, y in dislikes:
            g[x-1].append(y-1)
            g[y-1].append(x-1)
        colors = [0] * n
        for i in range(n):
            if colors[i] == 0 and not self.dfs(g, i, 1, colors):
                return False
        return True

time O(V+E) space O(V+E)