矩阵中的最大正方形

简介: 给定一个N*N的矩阵matrix,只有0和1两种值,返回边框全是1的最大正方形的边 长长度。

一、题目描述:


给定一个N*N的矩阵matrix,只有0和1两种值,返回边框全是1的最大正方形的边 长长度。


示例:

0   1   1   1    1

0   1   0   0   1

0   1   0   0   1

0   1   1   1   1

0   1   0   1   1


其中边框全是1的最大正方形的大小为4*4,所以返回4。


二、思路分析:


在N * N 的矩阵中,想要获取一个正方形,它的数量级为O(n^3)。两个循环可以确定左上角的点,再使用一个循环列举它的边长。 如果确定边框全是1的话还需要再遍历正方形,来判断它是否是边长为1的正方形。


在遍历边长的时候,我们可以利用两个预处理数组,将复杂度降低一个等级。定义right[i][j]记录右边连续出现1的个数,down[i][j]记录下方连续出现1的个数。


网络异常,图片无法展示
|
这样,在比较时,我们确定好左上角的点m[i][j]后,只需要判断左上角往右移边长个点,判断该点出现1的次数是否大于边长;判断左上角往下数边长个点出现1的次数大于等于边长;其他同理。


注意点


在预处理数组的时候,需要初始化两个数组right、down。一开始使用fill填充0的时候,发现获取预处理数组的结果不对,后来搜索问题后,发现fill属于浅拷贝,对象指向的都是同一个内存地址,一个变动,多个一起变动。

所以后来使用了from来初始化数组。


三、AC 代码:


function calculate(m) {
  let n = m.length
  let right = Array.from(Array(n), () => Array.from(Array(n), () => 0))
  let down = Array.from(Array(n), () => Array.from(Array(n), () => 0))
  setBorderMap(m, right, down)
  for (let size = Math.min(m.length, m[0].length); size != 0; size--) {
    if (hasSizeBorder(size, right, down)) {
      return size
    }
  }
  return 0
}
function hasSizeBorder(size, right, down) {
  for (let i = 0; i <= right.length - size; i++) {
    for (let j = 0; j <= right[0].length - size; j++) {
      if (
        right[i][j] >= size &&
        down[i][j] >= size &&
        right[i + size - 1][j] >= size &&
        down[i][j + size - 1] >= size
      ) {
        return true
      }
    }
  }
  return false
}
function setBorderMap(m, right, down) {
  let c = m[0].length,
    r = m.length
  if (m[r - 1][c - 1] === 1) {
    right[r - 1][c - 1] = 1
    down[r - 1][c - 1] = 1
  }
  for (let i = r - 2; i != -1; i--) {
    if (m[i][c - 1] == 1) {
      right[i][c - 1] = 1
      down[i][c - 1] = down[i + 1][c - 1] + 1
    }
  }
  for (let i = c - 2; i != -1; i--) {
    if (m[r - 1][i] == 1) {
      right[r - 1][i] = right[r - 1][i + 1] + 1
      down[r - 1][i] = 1
    }
  }
  for (let i = r - 2; i >= 0; i--) {
    for (let j = c - 2; j >= 0; j--) {
      if (m[i][j] === 1) {
        right[i][j] = right[i][j + 1] + 1
        down[i][j] = down[i + 1][j] + 1
      }
    }
  }
}


四、总结:


利用预处理数组,降低复杂度。可以避免三次循环后再使用一个循环确定边长是否均为1。


作者:ClyingDeng

链接:https://juejin.cn/post/6952738527066980388

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

目录
相关文章
|
20天前
线代的几何意义(一)——向量,坐标,矩阵
线代的几何意义(一)——向量,坐标,矩阵
|
21天前
10x10 矩阵
【10月更文挑战第26天】10x10 矩阵。
9 2
圆角三角形,二次方贝塞尔曲线
圆角三角形,二次方贝塞尔曲线
|
6月前
玩转矩阵
玩转矩阵
|
算法 Python
线代矩阵问题
线代矩阵问题
110 0
给定圆的半径r,求圆的面积。
给定圆的半径r,求圆的面积。
133 0
求线段的法向量
求线段的法向量
337 0
|
Windows
详解扬氏矩阵
详解扬氏矩阵
174 0
详解扬氏矩阵
|
机器学习/深度学习
矩阵相关练习
矩阵相关练习
矩阵相关练习
20天刷题计划-542. 01 矩阵
给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。 两个相邻元素间的距离为 1 。