LeetCode 886. Possible Bipartition?

263 篇文章 1 订阅
21 篇文章 0 订阅
这篇博客探讨了如何使用图论中的二分图染色算法解决将一组人分成两个不包含互相不喜欢的人的组的问题。首先尝试使用两个哈希集合构建无向图,但该方法未能成功。接着,博主介绍了使用深度优先搜索(DFS)和广度优先搜索(BFS)的方法。虽然BFS解决方案未被接受,但DFS成功实现了这一目标。代码示例中展示了两种不同的DFS解决方案,用于检查是否可以将所有节点分配到两个满足条件的组中。
摘要由CSDN通过智能技术生成

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.

so the problem is easy to understand actually:
there are a group of nodes, and if they are dislike each other, it will be on int[][] dislike array. for people dislike each other, we should let them in different group
now we need to check if we can divide those group of people into just two.

idea:
use two hashset as graphs, because it’s easy to judge if this node is in this graph or not.
suppose we are in the middle of construct those two graphs, for each new array in dislike, we check if those two are in any of these graph or not, if both of them are not in, then we put them in(but which to which? it will actually effect later we add other nodes that may not compatible with them), so this solution doesn’t work.
now what should we do?

we should construct the graph based on this dislike, and use dfs to iterate the whole graph, and we give current node and it’s neighbor with different color(if this neighbor hasn’t colored yet, but if it is colored, then we need to check if the color is the same with current node, if it is the same, then we can just return false)
but let’s try to write the code in BFS.
but strangely, this BFS solution can’t get accepted but the DFS can:

class Solution {
    public boolean possibleBipartition(int N, int[][] dislikes) {
        List<Integer>[] graph = new ArrayList[N];
        
        for (int i = 0; i<N; i++) {
            graph[i] = new ArrayList<>();
        }
        
        int m = dislikes.length;
        for (int i = 0; i < m; i++) {
            int node1 = dislikes[i][0] - 1;
            int node2 = dislikes[i][1] - 1;
            
            graph[node1].add(node2); //undirected graph, so we have to add them all
            graph[node2].add(node1);
        }
        
        int[] color = new int[N]; //this is actually like visited
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(0); //actually we can start with any node from 0 to N-1
        color[0] = 1; // and we have to pick a color for node 0 too
        
        
        while (!queue.isEmpty()) {
            System.out.println("x");
            int cur = queue.poll();
            int curColor = color[cur];
    
            int size = graph[cur].size();
            for (int i = 0; i < size; i++) {
                int neigh = graph[cur].get(i);
                int neighColor = color[neigh];
                if (neighColor == 0) { //that means we haven't visited it
                    color[neigh] = curColor == 1? -1: 1; //assign new value on color[neigh] instead of neighColor
                    queue.offer(neigh);
                } else { //if we visited it, then we don't have to offer it in the queue again
                    if (neighColor == curColor) {
                        return false;
                    }
                }
                
            }
        }
        return true;
    }
    
    
}

DFS accepted solution:

    public boolean possibleBipartition(int N, int[][] dislikes) {
        List<Integer>[] graph = new ArrayList[N]; //graph is [list1, list2, list3...]
        for (int i = 0; i < N; i++) graph[i] = new ArrayList<>(N); //initialize each one of them, it is not necessary
        for (int i = 0; i < dislikes.length; i++) {
            int a = dislikes[i][0] - 1; //project input to graph we can easily use
            int b = dislikes[i][1] - 1;
            graph[a].add(b);
            graph[b].add(a);
        }
        int[] color = new int[N];
        color[0] = 1;
        for (int i = 0; i < N; i++) {
            if (!dfs(graph, i, color)) return false;
        }
        return true;   
    }
    
    private boolean dfs(List<Integer>[] graph, int node, int[] color) {
        for (int i = 0; i < graph[node].size(); i++) { //for every neighbor of current node
            int op = graph[node].get(i); 
            if (color[op] == 0) { //if it hasn't been colored yet
                color[op] = color[node] == 1 ? 2 : 1; //then we choose the opposite of the node
                if (!dfs(graph, op, color)) return false; //we continue the dfs trip
            } else { //if the neighbor is colored, then we should leave it unless it has the same color as the current node
                if (color[op] == color[node]) return false;
            }
        }
        return true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值