[Leetcode934]最短的桥

1.题目

给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。

 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。

你可以将任意数量的 0 变为 1 ,以使两座岛连接起来,变成 一座岛 。

返回必须翻转的 0 的最小数目。

 

示例 1:

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

示例 2:

输入:grid = [[0,1,0],[0,0,0],[0,0,1]]
输出:2

示例 3:

输入:grid = [[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

 

提示:

  • n == grid.length == grid[i].length
  • 2 <= n <= 100
  • grid[i][j] 为 0 或 1
  • grid 中恰有两个岛

2.思路

本题的思路为使用并查集划分岛屿,及使用广度搜索找到2个岛的路径。

2.1 并查集的实现

2.1.1 初始化

初始时,每个元素都位于一个单独的集合,表示为一棵只有根节点的树。方便起见,我们将根节点的父亲设为自己。

public void init(int nums[])
{
        int length=nums.length;
        for(int i=0;i<length;i++)
            nums[i]=i;
 }

2.1.2 合并

如果两个元素原先是在两个不同集合,经过判断是在同一个集合,则需要将两个集合进行合并。Notes:合并需要改动他们的根节点的指向即可,否则单纯改动叶子结点会成环。

public void union(int nums[],int m,int n)//合并
{
        find(n,nums)=find(m,nums);
 }

2.1.3 查询

找到集合中的根节点,查询过程中经过的每个元素都属于该集合,我们可以将其直接连到根节点以加快后续查询。

public int find(int n,int nums[])//查询
 {
       return n==nums[n] ? n:(nums[n]=find(nums[n],nums));
}

2.2 广度搜索

需要设置每个元素是否有被遍历,及一个初始值为岛1的队列,从岛1出发找到岛2的值,找到即停止,返回路径最小值。在广度遍历的过程中,将遍历的值加入队列。并更新到达这个值的距离。

        //BFS
 int min=0;
while(!List1.isEmpty())
{
   int index=List1.poll();
   int i=index/len;
   int j=index%len;
   if((j+1)<len && fw[i][j+1] == false)
    {
       int a=i*len+j+1;
       List1.offer(i*len+j+1);
       dis[i][j+1]=dis[i][j]+1;
       fw[i][j+1]=true;
       if(List2.indexOf(a)!=-1)
       {
            System.out.println("j+1:"+i+j);
            return dis[i][j+1]-1;
        }
      }
        if((i+1)<len && fw[i+1][j] == false)
         {
                int a=(i+1)*len+j;
                List1.offer((i+1)*len+j);
                dis[i+1][j]=dis[i][j]+1;
                fw[i+1][j]=true;
                if(List2.indexOf(a)!=-1)
                {
                    System.out.println("i+1:"+i+j);
                    return dis[i+1][j]-1;
                }
            }
             if((i-1)>=0 && fw[i-1][j]==false)
            {
                int a=(i-1)*len+j;
                List1.offer(a);
                fw[i-1][j]=true;
                dis[i-1][j]=dis[i][j]+1;
                if(List2.indexOf(a)!=-1)
                {
                    System.out.println("i-1:"+i+j);
                    return dis[i-1][j]-1;
                }
            }
            if((j-1)>=0 && fw[i][j-1]==false)
            {
                int a=i*len+j-1;
                fw[i][j-1]=true;
                List1.offer(i*len+j-1);
                dis[i][j-1]=dis[i][j]+1;
                if(List2.indexOf(a)!=-1)
                {
                    System.out.println("j-1:"+i+j);
                    return dis[i][j-1]-1;
                }
            }
        }

3.实现代码

class Solution {
    public void init(int nums[])
    {
        int length=nums.length;
        for(int i=0;i<length;i++)
            nums[i]=i;
    }
    public int find(int n,int nums[])//查询
    {
        return n==nums[n] ? n:(nums[n]=find(nums[n],nums));
    }
    public void union(int nums[],int m,int n)//合并
    {
        //nums[find(n,nums)]=nums[m];
       // nums[n]=nums[m];
        int length=nums.length;
        for(int i=0;i<length;i++)
            if(nums[i] ==nums[n])
                nums[i]=nums[m];
        
    }
    public int shortestBridge(int[][] grid) {
        int len=grid.length;
        int length=len*len;
        int nums[]=new int[length];
        init(nums);
        int flag=0;
        for(int i=0;i<len;i++)
            for(int j=0;j<len;j++)
            {
                int m=i*len+j;
                if(grid[i][j] ==1 && flag==0)//岛内第一个元素
                    flag=1;
                else if(grid[i][j] ==1 && flag==1)
                {
                    if(i==0 && grid[0][j-1] == 1)
                        union(nums,j-1,m);
                    else if(j==0 && grid[i-1][0]==1)
                        union(nums,(m-len),m);
                    else if(i>0 && j>0)
                    {
                        int x=(i-1)*len+j;
                        if(grid[i-1][j]==1)
                            union(nums,x,m);
                        if(grid[i][j-1]==1)
                            union(nums,m-1,m);
                    }
                    //System.out.println("m:"+m+"nums:"+nums[m]);
                }
                else if(grid[i][j] == 0)nums[m]=-1;
            }
        Queue<Integer> List1=new LinkedList<Integer>();
        ArrayList<Integer> List2=new ArrayList<Integer>();
        flag=-2;
        int dis[][]=new int[len][len];
        boolean fw[][]=new boolean[len][len];
        for(int i=0;i<length;i++)
        {
            if(nums[i]!=-1 && flag==-2 || nums[i] == flag)
            {
                
                List1.offer(i);
                flag=nums[i];
                int x=i/len;
                int y=i%len;
                fw[x][y]=true;
            }
            else if(nums[i]!=-1 && nums[i]!=flag)
                {
                    List2.add(i);
                }
        }
        int List1Lens=List1.size();
        //BFS
        int min=0;
        while(!List1.isEmpty())
        {
            int index=List1.poll();
            int i=index/len;
            int j=index%len;
            if((j+1)<len && fw[i][j+1] == false)
            {
                int a=i*len+j+1;
                List1.offer(i*len+j+1);
                dis[i][j+1]=dis[i][j]+1;
                fw[i][j+1]=true;
                if(List2.indexOf(a)!=-1)
                {
                    System.out.println("j+1:"+i+j);
                    return dis[i][j+1]-1;
                }
            }
            if((i+1)<len && fw[i+1][j] == false)
            {
                int a=(i+1)*len+j;
                List1.offer((i+1)*len+j);
                dis[i+1][j]=dis[i][j]+1;
                fw[i+1][j]=true;
                if(List2.indexOf(a)!=-1)
                {
                    System.out.println("i+1:"+i+j);
                    return dis[i+1][j]-1;
                }
            }
             if((i-1)>=0 && fw[i-1][j]==false)
            {
                int a=(i-1)*len+j;
                List1.offer(a);
                fw[i-1][j]=true;
                dis[i-1][j]=dis[i][j]+1;
                if(List2.indexOf(a)!=-1)
                {
                    System.out.println("i-1:"+i+j);
                    return dis[i-1][j]-1;
                }
            }
            if((j-1)>=0 && fw[i][j-1]==false)
            {
                int a=i*len+j-1;
                fw[i][j-1]=true;
                List1.offer(i*len+j-1);
                dis[i][j-1]=dis[i][j]+1;
                if(List2.indexOf(a)!=-1)
                {
                    System.out.println("j-1:"+i+j);
                    return dis[i][j-1]-1;
                }
            }
        }
        return 0;
    }
}

 

posted @ 2022-10-27 15:25  追·不逝  阅读(37)  评论(0编辑  收藏  举报