leetcode 886. 可能的二分法

leetcode 886. 可能的二分法

题目:
给定一组 n 人(编号为 1, 2, …, n), 我们想把每个人分进任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。
给定整数 n 和数组 dislikes ,其中 dislikes[i] = [ai, bi] ,表示不允许将编号为 ai 和 bi的人归入同一组。当可以用这种方法将所有人分进两组时,返回 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

解体思路

利用 dp + 染色法
从第一个1遍历到n , 假设数组n = 10,dislikes = [[1,2],[3,4],[5,6],[6,7],[8,9],[7,8]]为例
row 1 开始遍历 , 遍历到第二列发现冲突 ,这时将1放入a组.
然后开始dp, 直接遍历第二行(冲突点) , 先将2放入b组(和a组冲突的组) , 然后继续遍历,发现没有冲突点 .
因为第二行已经被分配了组,所以直接遍历第三行

在这里插入图片描述

结果:
a组: 1,3,5,7,9
b组: 2,4,6,8

class Solution {
    public boolean possibleBipartition(int n, int[][] dislikes) {
        int[][] pic = new int[n+1][n+1];  //创建二维数组,用来查看冲突!
        for(int[] p:dislikes){
            pic[p[0]][p[1]] = pic[p[1]][p[0]] = 1;  //1表示冲突
        }   
        int[] record = new int[n+1];
        for(int i=1 ; i<=n ; i++){
            //record[i] == 0 表示通过dp分过组的元素就不用看了,再看会重复分组 
            //dislikes = [[1,2],[3,4],[5,6],[6,7],[8,9],[7,8]]为例
            //遍历第一行会给2分组 = > 1在1组,2在-1组
            //如果遍历第二行再进去 => 2分到1组,直接冲突!!
            if(record[i] == 0 && !dfs(pic,record,i,1,n)){

                return false;
            }
        }
        return true;
    }
    public boolean dfs(int[][] matrix, int[] record, int index, int group, int n){
            record[index] = group;
            for(int i=1;i<=n;i++){
                if(i==index) continue; //自己和自己不管
                if(matrix[index][i]==1 && record[i] == group){ //发生冲突,且分过组,和当前下标元素在同一组!
                    return false;
                }
                if(matrix[index][i]==1 && record[i] == 0 && !dfs(matrix,record,i,group*-1,n)){
                    //发生冲突,未分过组,分组之后会发生冲突!!
                    return false;
                }
            }
            return true;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值