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

前言

很多面试算法题都涉及0 ,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矩阵中岛的个数和0,1矩阵的最大连续全1块(可以非规则)_第1张图片

解题思路

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

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

代码

import java.util.Random;

/*需求:对于一个只有0和1的二维矩阵,上下或者左右相邻元素都为1则为一块(斜着不算),求一共有多少取值为1的连续块.如下图:
 * 
 *   0 1 0 1 1 0
 *   1 1 0 0 1 1
 *   0 0 1 0 0 0
 *   1 1 0 0 0 0
 * 
 * 上图中有4块
 */

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

    // 生成指定的随机矩阵,计算块数
    private static void creatRect() {
        // 设定矩阵的高和宽
        int h = 8;
        int w = 8;
        // 生成指定随机矩阵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));
    }

    // 判断连续块,递归
    private static void block(int i, int j) {
        // 修改(i,j)坐标对应的数组元素的值(避免递归时反复判断相邻元素)
        rect[i][j] = 4;
        // 分别判断上下左右
        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
第二遍 如果 遇到不为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
最后一遍 数一下各种数字的个数,最多的,就是最大全1子块的面积。(注,这样做,结果是连续的全1区域,很可能是不规则的)

你可能感兴趣的:(算法,java,python)