JAVA程序设计:最短的桥(LeetCode:934)

在给定的二维二进制数组 A 中,存在两座岛。(岛是由四面相连的 1 形成的一个最大组。)

现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛。

返回必须翻转的 0 的最小数目。(可以保证答案至少是 1。)

 

示例 1:

输入:[[0,1],[1,0]]
输出:1
示例 2:

输入:[[0,1,0],[0,0,0],[0,0,1]]
输出:2
示例 3:

输入:[[1,1,1,1,1],[1,0,0,0,1],[1,0,1,0,1],[1,0,0,0,1],[1,1,1,1,1]]
输出:1
 

提示:

1 <= A.length = A[0].length <= 100
A[i][j] == 0 或 A[i][j] == 1

思路:我们先用dfs找出来两个岛,之后通过bfs判断两岛之间的最短距离。

class Solution {
	
	class node{
		int r,c,d;
		public node(int r,int c,int d) {
			this.r=r;
			this.c=c;
			this.d=d;
		}
	}
	
    public int shortestBridge(int[][] A) {

    	int m=A.length;
    	int n=A[0].length;
    	int[][] colors=get(A);
    	Queue<node> q=new LinkedList<>();
    	Set<Integer> target=new HashSet<>();
    	
    	for(int i=0;i<m;i++)
    		for(int j=0;j<n;j++) {
    			if(colors[i][j]==1)
    				q.add(new node(i,j,0));
    			else if(colors[i][j]==2)
    				target.add(i*n+j);
    		}
    	
    	while(!q.isEmpty()) {
    		node now=q.poll();
    		if(target.contains(now.r*n+now.c))
    			return now.d-1;
    		for(int nei : neighbor(A,now.r,now.c)) {
    			int r=nei/n,c=nei%n;
    			if(colors[r][c]!=1) {
    				q.add(new node(r,c,now.d+1));
    				colors[r][c]=1;
    			}
    		}
    	}
    	
    	return -1;
    }
    
    private int[][] get(int[][] a){
    	
    	int m=a.length;
    	int n=a[0].length;
    	int[][] colors=new int[m][n];
    	int t=0;
    	
    	for(int i=0;i<m;i++)
    		for(int j=0;j<n;j++) 
    			if(colors[i][j]==0 && a[i][j]==1) {
    				Stack<Integer> st=new Stack<>();
    				st.push(i*n+j);
    				colors[i][j]=++t;
    				
    				while(!st.isEmpty()) {
    					int node=st.pop();
    					int r=node/n,c=node%n;
    					for(int nei : neighbor(a,r,c)) {
    						int rr=nei/n,cc=nei%n;
    						if(a[rr][cc]==1 && colors[rr][cc]==0) {
    							colors[rr][cc]=t;
    							st.push(rr*n+cc);
    						}
    					}
    				}
    			}
    	
    	return colors;
    }
    private List<Integer> neighbor(int[][] a,int r,int c){
    	int R=a.length;
    	int C=a[0].length;
    	List<Integer> ans=new ArrayList<>();
    	if(0<=r-1) ans.add((r-1)*R+c);
    	if(0<=c-1) ans.add(r*R+c-1);
    	if(r+1<R) ans.add((r+1)*R+c);
    	if(c+1<C) ans.add(r*R+c+1);
    	return ans;
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值