这里是题目描述:LeetCode-999.由斜杠划分区域
方法1:dfs方法
本解法参考LeetCode官网题解【图解算法】三种详细解法!中的方法1
大体步骤是:将NxN网格中的每个1x1方块划分成3x3的更小的方格,整个网格就被划分成了(3N)x(3N)个更小的方格。然后将各个对角线斜杠上填充1
来代表斜杠,其余部分全部填充为0
。这样,问题就转化成了求整个(3N)x(3N)网格中有几个0
连通块,可以用dfs来求得连通块个数
更详细的描述见上面的参考题解链接题解
dfs方法题解代码:
public class Solution {
public int regionsBySlashes(String[] grid) {
int N=grid.length;
int[][] board=new int[3*N][3*N]; //每个网格分割成3*3的小网格
for(int i=0;i<grid.length;i++) //遍历grid中的斜杠信息,将board中对应的斜线位置从0置1
{
for(int j=0;j<grid[i].length();j++)
{
char ch=grid[i].charAt(j);
if(ch=='/')
{
int row=i*3,line=j*3+2;
for(int k=0;k<3;k++,row++,line--)
{
board[row][line]=1;
}
}
else if(ch=='\\')//ch=='\'
{
int row=i*3,line=j*3;
for(int k=0;k<3;k++,row++,line++)
{
board[row][line]=1;
}
}
}
}
int res=0;
for(int i=0;i<board.length;i++)
{
for(int j=0;j<board[i].length;j++)
{
if(board[i][j]==0)
{
res+=1;
dfs(board,i,j);
}
}
}
return res;
}
void dfs(int[][] board,int r,int l) //深度优先遍历一个连同的0区域
{
board[r][l]=1;
//上下左右四个方向搜索
if(r>0 && board[r-1][l]==0)
{
dfs(board,r-1,l);
}
if(r<board.length-1 && board[r+1][l]==0)
{
dfs(board,r+1,l);
}
if(l>0 && board[r][l-1]==0)
{
dfs(board,r,l-1);
}
if(l<board[r].length-1 && board[r][l+1]==0)
{
dfs(board,r,l+1);
}
}
}
方法2:并查集法
本题参考LeetCode官网题解
关于官方 并查集 题解 的 自我理解 加 补充 JAVA 和 【图解算法】三种详细解法!中的方法2
并查集法的具体过程步骤见上面两个参考题解
并查集法题解代码:
class Solution {
Patch[] patch;
HashMap<Integer, HashSet<Integer>> unionFindSets;
public int regionsBySlashes(String[] grid) {
int N=grid.length;
patch=new Patch[N*N*4];
unionFindSets=new HashMap<>();
for(int i=0;i<N*N*4;i++) //将每个方块的4个区域初始化为一个集合,rootId是它本身的id
{
patch[i]=new Patch(i,i);
HashSet<Integer> set=new HashSet<>();
set.add(i);
unionFindSets.put(i,set);
}
for(int i=0;i<grid.length;i++)
{
String s=grid[i];
for(int j=0;j<s.length();j++)
{
int index=i*N*4+j*4;
char ch=s.charAt(j);
if(ch=='/') //分别合并本方块中的0、1和2、3
{
mergeSet(index+0,index+1);
mergeSet(index+2,index+3);
}
else if(ch=='\\') //分别合并本方块中的0、3和1、2
{
mergeSet(index+0,index+3);
mergeSet(index+1,index+2);
}
else //ch==' ',将本方格中的0、1、2、3合并为一个
{
mergeSet(index+0,index+1);
mergeSet(index+0,index+2);
mergeSet(index+0,index+3);
}
}
}
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
int index=i*N*4+j*4;
if(j<N-1) //3和右边的方格的1合并
{
int index2=i*N*4+(j+1)*4;
int root=patch[index+3].rootId;
int root2=patch[index2+1].rootId;
if(unionFindSets.get(root).size()>=unionFindSets.get(root2).size())
{
mergeSet(root,root2);
}
else
{
mergeSet(root2,root);
}
}
if(i<N-1) //2和下边的方格的0合并
{
int index3=(i+1)*N*4+j*4;
int root=patch[index+2].rootId;
int root3=patch[index3].rootId;
if(unionFindSets.get(root).size()>=unionFindSets.get(root3).size())
{
mergeSet(root,root3);
}
else
{
mergeSet(root3,root);
}
}
}
}
return unionFindSets.size();
}
void mergeSet(int root1,int root2) //合并两个集合
{
if(root1==root2)
{
return;
}
HashSet<Integer> set1=unionFindSets.get(root1);
HashSet<Integer> set2=unionFindSets.get(root2);
for(int id:set2)
{
set1.add(id);
patch[id].rootId=root1;
}
unionFindSets.remove(root2);
}
}
class Patch
{
int id;
int rootId;
public Patch(int id, int rootId) {
this.id = id;
this.rootId = rootId;
}
}