JAVA程序设计:由斜杠划分区域(LeetCode:959)

在由 1 x 1 方格组成的 N x N 网格 grid 中,每个 1 x 1 方块由 /、\ 或空格构成。这些字符会将方块划分为一些共边的区域。

(请注意,反斜杠字符是转义的,因此 \ 用 "\\" 表示。)。

返回区域的数目。

 

示例 1:

输入:
[
  " /",
  "/ "
]
输出:2
解释:2x2 网格如下:

示例 2:

输入:
[
  " /",
  "  "
]
输出:1
解释:2x2 网格如下:

示例 3:

输入:
[
  "\\/",
  "/\\"
]
输出:4
解释:(回想一下,因为 \ 字符是转义的,所以 "\\/" 表示 \/,而 "/\\" 表示 /\。)
2x2 网格如下:

示例 4:

输入:
[
  "/\\",
  "\\/"
]
输出:5
解释:(回想一下,因为 \ 字符是转义的,所以 "/\\" 表示 /\,而 "\\/" 表示 \/。)
2x2 网格如下:

示例 5:

输入:
[
  "//",
  "/ "
]
输出:3
解释:2x2 网格如下:

提示:

1 <= grid.length == grid[0].length <= 30
grid[i][j] 是 '/'、'\'、或 ' '。

思路:我们考虑将网格中的每一格看做由左划线或者右划线分成的两格,而垂直方向仍然正常,此时我们得到了一个m*(2n)的网格图,这样我们可以通过左划线或者右划线判断哪些网格时连通的,而对于连通合并的操作我们采用并查集。

注意:对于竖直方向连通情况较复杂,代码中由不懂的地方可以留言。

class Solution {
	
	private int[] f;
	
    public int regionsBySlashes(String[] grid) {
    	
    	int ans=0;
    	int m=grid.length;
    	int n=grid[0].length()*2;
    	int size=m*n;
    	f=new int[size];
    	boolean[] flag=new boolean[size];
    	
    	for(int i=0;i<size;i++)
    		f[i]=i;
    	
    	for(int i=0;i<m;i++)
    		for(int j=0;j<n;j+=2) {
    			if(grid[i].charAt(j/2)==' ')
    				merge(i*n+j,i*n+j+1);
    			if(j>0) 
    				merge(i*n+j-1,i*n+j);
    		}
    	
    	for(int j=0;j<n;j+=2)
    		for(int i=0;i<m-1;i++) {
    			if((grid[i+1].charAt(j/2)=='\\' || grid[i+1].charAt(j/2)==' ')
    					&& (grid[i].charAt(j/2)=='/' || grid[i].charAt(j/2)==' '))
    				merge(i*n+j+1,(i+1)*n+j+1);
    			else if((grid[i+1].charAt(j/2)=='\\' || grid[i+1].charAt(j/2)==' ')
    					&& (grid[i].charAt(j/2)=='\\' || grid[i].charAt(j/2)==' '))
    				merge(i*n+j,(i+1)*n+j+1);
    			else if((grid[i+1].charAt(j/2)=='/' || grid[i+1].charAt(j/2)==' ')
    					&& (grid[i].charAt(j/2)=='\\' || grid[i].charAt(j/2)==' '))
    				merge(i*n+j,(i+1)*n+j);
    			else if((grid[i+1].charAt(j/2)=='/' || grid[i+1].charAt(j/2)==' ')
    					&& (grid[i].charAt(j/2)=='/' || grid[i].charAt(j/2)==' '))
    				merge(i*n+j+1,(i+1)*n+j);
    		}
    	
    	for(int i=0;i<m;i++)
    		for(int j=0;j<n;j++) {
    			int index=find(i*n+j);
    			if(flag[index])
    				continue;
    			ans++;
    			flag[index]=true;
    		}
    	
    	return ans;
    }
    
    private void merge(int x,int y) {
    	int t1=find(x);
    	int t2=find(y);
    	if(t1!=t2)
    		f[t1]=t2;
    }
    
    private int find(int x) {
    	if(f[x]==x)
    		return x;
    	return f[x]=find(f[x]);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值