Java/886.可能的二分法(Possible Bipartition)

45 篇文章 0 订阅
14 篇文章 0 订阅

 

这道题花了不少时间,一开始没有找对方法,以为直接遍历就完了。吃了大亏后,查了不少资料才知道要用染色(覆盖)算法来做——(有贪心算法和回溯算法两种)此处我用的是回溯算法。

class Solution {

	private Map<Integer , List<Integer>> graph = new HashMap<>();   // 图存放的数据结构
	private int[] color;                                            // 每个节点的颜色
	
    public boolean possibleBipartition(int N, int[][] dislikes) {
    
    	color = new int[N + 1];
    	Arrays.fill(color , - 1);
    	for (int i = 1;i <= N;i ++) {
    		graph.put(i , new ArrayList<>());
    	}
    	for (int[] edge : dislikes) {                    // 将图存入Map   
    		int from = edge[0] , to = edge[1];
    		graph.get(from).add(to);
    		graph.get(to).add(from);
    	}
    	for (int i = 1;i <= N;i ++) {                   // 未判断的节点进行判断
    		if (color[i] < 0) {
    			color[i] = 0;
    			if (!dfs(i)) {
    				return false;
    			}
    		}
    	}
    	return true;
    	
    }
	
    private boolean dfs(int current) {
    	
    	for (int next : graph.get(current)) {    	
    		if (color[next] < 0) {
    			color[next] = 1 - color[current];       //第一圈为1 第二圈为0 第三圈为1 依次类推(主要是为了判断相邻的两个层会不会染色冲突)
    			if (!dfs(next)) {                       // 判断 下一节点染色是否成功 ,失败则返回false
    				return false;
    			}
    		} else if (color[next] == color[current]) {
    			return false;                           //发现Vi 与 Vi-1 节点颜色相同
    		}
    	}
    	return true;
    	
    }
}

思路:本题类似于经典的染色算法,使用DFS(深度遍历)思路解题(不知的这个的自行百度,类似走迷宫的思想),首先将限制条件转换为一个图,将color[] 赋予初始值-1,color的长度为可以使用颜色的数量。

(本做法首先要理解:题目给出的N相当于,给出了N个节点,每个节点一个颜色,所以共有N个节点,N个颜色。我们是在此前提下,判断 “不允许分组”构成的图,判断相邻的两个节点是否不同颜色)

DFS思路:

  1. 染色的过程是第一圈,第二圈,第三圈......以此类推进行染色判定
  2. 遍历所有节点的过程,对其进行染色标记,第一圈为 0 ,第二圈为 1-0,第三圈为1-(1-0)=0 , 第四圈为 1-0 其实是相邻的两圈进行判断,若Q1 = Q2 则说明在N个颜色的条件下,无法满足对限制条件图进行染色判定。
  3. 进行深度遍历时,若节点未进行染色判定,进行染色判定,直到到达最后一个节点,没有下一个节点时返回true,(途中染色判定失败直接返回)。

当所有节点都进行染色判定后,途中没有失败时,说明条件可以进行二分算法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值