0,1矩阵的最大连续1块和全部连续1块的个数(可以非规则)

60 篇文章 1 订阅

前言

寻找0 ,1矩阵中含有连续全1块的个数(岛的个数)和0, 1矩阵中最大连续的全1块。

定义

0 ,1矩阵中含有连续全1块的个数

一个矩阵中只有0和1两种值, 每个位置都可以和自己的上、 下、 左、 右

四个位置相连, 如果有一片1连在一起, 这个部分叫做一个岛, 求一个 矩阵中有多少个岛?

举例:

0 0 1 0 1 0
1 1 1 0 1 0
1 0 0 1 0 0
0 0 0 1 0 0

这个矩阵中有三个岛。即0, 1矩阵中最大连续的全1块有三个。

在全1块中1的个数最多的块定义为0,1矩阵的最大连续全1块,上述矩阵的最大全1块是5,下图给个明显的示例:
在这里插入图片描述

解题思路

0 ,1矩阵中含有连续全1块的个数

运用了一些递归的思想,首先是双层for循环逐个遍历矩阵的元素.找到某个元素为1的时候,利用递归的思想将这个元素的上下左右,和它相邻的为1的上下左右元素,和相邻的相邻的…. 这些元素改为0,最后返回num

package Exercises;

import java.util.Random;

/**
 * ClassName findMaxOne
 * Author  Lin
 * Date 2019/4/16 20:43
 **/

public class findMaxOne {
    // 共享成员变量,矩阵
    static int[][] rect = null;
    // 主函数
    public static void main(String[] args) {
        creatRect();
    }

    // 生成指定的随机矩阵,计算块数
    private static void creatRect() {
        // 设定矩阵的高和宽
        int h = 12;
        int w = 12;
        // 生成指定随机矩阵int[i][j],并展示在控制台;将元素值为1的元素存入List,并展示在控制台
        Random rdm = new Random();
        rect = new int[h][w];
        System.out.println("随机生成矩阵如下图:");
        for (int i = 0; i < rect.length; i++) {
            for (int j = 0; j < rect[i].length; j++) {
                int k = rdm.nextInt(2);
                rect[i][j] = k;
                System.out.print(" " + rect[i][j]);
            }
            System.out.println();
        }
        System.out.println("开始进行计算");
        // 开始计时
        long time = System.currentTimeMillis();
        // 计数
        int count = 0;
        // 遍历矩阵找1,块的定位
        for (int i = 0; i < rect.length; i++) {
            for (int j = 0; j < rect[i].length; j++) {
                // 当找到1时,开始处理其所在的块
                if (rect[i][j] == 1) {
                    block(i, j);
                    count++;
                }
            }
        }
        // 输出块数
        // System.out.println("计算结束");
        System.out.println("该矩阵中,共有" + count + "块");
        // 输出计时结果
        System.out.println("计算用时(ms):" + (System.currentTimeMillis() - time));
        System.out.println("最终结果如下图:");
        for (int i = 0; i < rect.length; i++) {
            for (int j = 0; j < rect[i].length; j++) {
                System.out.print(" " + rect[i][j]);
            }
            System.out.println();
        }
    }

    // 判断连续块,递归
    private static void block(int i, int j) {
        // 修改(i,j)坐标对应的数组元素的值(避免递归时反复判断相邻元素)
        rect[i][j] = 4;
        /*System.out.println("结果如下图:");
        for (int ii = 0; ii < rect.length; ii++) {
            for (int jj = 0; jj < rect[ii].length; jj++) {
                System.out.print(" " + rect[ii][jj]);
            }
            System.out.println();
        }*/
        // 分别判断上下左右
        if (i < rect.length - 1 && rect[i + 1][j] == 1) {
            block(i + 1, j);
        }
        if (i > 0 && rect[i - 1][j] == 1) {
            block(i - 1, j);
        }
        if (j < rect[i].length - 1 && rect[i][j + 1] == 1) {
            block(i, j + 1);
        }
        if (j > 0 && rect[i][j - 1] == 1) {
            block(i, j - 1);
        }
    }

}

并查集思想

0,1矩阵的最大连续全1块
对矩阵做三次扫描, 扫描的次序都是从左到右,从上到下.第一遍将所有为1的元素,依次标一个值,这个值从1开始 例如:
0 0 0 0 0 // 0 0 0 0 0标注成这样
0 1 1 0 0 // 0 1 2 0 0
0 1 0 0 0 // 0 3 0 0 0
0 0 0 1 0 // 0 0 0 4 0
0 0 0 1 0 // 0 0 0 5 0

对应并查集的初始化:

if( nums[i][j] == 1){
      Len[i][j]++;
      Set[i][j] = index++;
      }

第二遍 如果 遇到不为0 的元素, 考虑这个元素以及它周围四个元素中,不为0的元素标,求他们的最小值,并将这些元素通标注为这个最小值 像上面,遇到了1 那么将 2和3 标注成 1 。就变成下面这样
0 0 0 0 0
0 1 1 0 0
0 1 0 0 0
0 0 0 4 0
0 0 0 4 0

对应并查集的合并操作

if(Set[i[j] != Set[i+offsetx][j+offsety]){
      if(Set[i][j] < Set[i+offsetx][j+offsety]){
	               Set[i+offsetx][j+offsety] = Set[i][j];
	               Len[i][j] += Len[i+offsetx][y+offsety];
               }
       else{
	                Set[i][j] = Set[i+offsetx][j+offsety];
	                Len[i+offsetx][y+offsety] += Len[i][j] ;
               }
    }

最后一遍 数一下各种数字的个数,最多的,就是最大全1子块的面积。(注,这样做,结果是连续的全1区域,很可能是不规则的)

Max = Math.max(Len[i[j], max);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值