题目

给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold。

请你返回元素总和小于或等于阈值的正方形区域的最大边长;如果没有这样的正方形区域,则返回 0 。

示例 1:

输入:mat = [[1,1,3,2,4,3,2],[1,1,3,2,4,3,2],[1,1,3,2,4,3,2]], threshold = 4
输出:2
解释:总和小于 4 的正方形的最大边长为 2,如图所示。
示例 2:

输入:mat = [[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2]], threshold = 1
输出:0
示例 3:

输入:mat = [[1,1,1,1],[1,0,0,0],[1,0,0,0],[1,0,0,0]], threshold = 6
输出:3
示例 4:

输入:mat = [[18,70],[61,1],[25,85],[14,40],[11,96],[97,96],[63,45]], threshold = 40184
输出:2

提示:

1 <= m, n <= 300
m == mat.length
n == mat[i].length
0 <= mat[i][j] <= 10000
0 <= threshold <= 10^5

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-side-length-of-a-square-with-sum-less-than-or-equal-to-threshold
整个题目,leetcode 的官方讲解非常清晰明了,包括了前缀和的等背景知识,推荐大家去看。

思路

这真是一个优秀的题目和优秀的解法, 有太多的细节都没有考虑到。主要涉及以下几点:
1、 怎么快速得到矩阵中任意子矩阵的元素和: 二维矩阵的前缀和
2、 python中当矩阵的indexh超出边界的时候, 例如 (-1, 1)的, 的时候怎么让它的值为0而不是第1列的最后一个元素: 将原始矩阵扩展一行一列,值为0, 从(1,1)开始遍历:
3、 怎么减少枚举的次数: 记录当前获得的小于阈值的最大的边长,接下来枚举中就不用遍历小于当前最大边长的值了。

矩阵的后缀和

数组的前缀和:设A = [a, b, c, d], 前缀和 P = [a, a+b, a+b+c, a+b+c+d];
前缀和数组的大小与原数组大小一致, 第i个元素的值为从第一个元素开始到第i个元素的累加;

矩阵的前缀和: 扩展到二维矩阵 A ,二维矩阵的前缀和矩阵 P 与原始矩阵等大, P 的第(i,j)个元素的值等于 [ 左上角坐标为(0,0), 右下角坐标为(i, j)的矩阵的元素之和 ] 。

如何快速求解矩阵的前缀和矩阵P : 按行的顺序进行遍历,当求解 P[i][j] 的时候, P[i-1] [j]、P[i][j-1]、P[i-1][j-1] 都已知了,按照求面积的相关原理(画个图看看一下,完全不用死记硬背):

P[i][j] = P[i-1][j]+P[i][j-1]+P[i-1][j-1]

在python编程中,具体的技巧就是结合上面思路中的第 2 点;

如何利用前缀和快速求解任意字矩阵的元素之和:同样按照求面积的原理,假设求矩形左上角(x1, y1) 到 矩形右下角(x2, y2)之间的元素之和, A[i][j],P[i - 1][j],P[i][j - 1] 和 P[i - 1][j - 1] 均已知(画个图看看一下,完全不用死记硬背):

S = P[x2][y2] - P[x1-1][y1]-P[x2][y1-1]+P[x1-1][y1-1]

以上知识理解了以后,就可以开始枚举矩形中的所有正方形了, 结合代码来讲:

代码

class Solution(object):def maxSideLength(self, mat, threshold):""":type mat: List[List[int]]:type threshold: int:rtype: int"""# the size of matrow = len(mat)col = len(mat[0])# 求解前缀和矩阵P, 输入的矩阵大小是mat的 row 和 col , 但是实际的 返回的P的大小是 row+1  和 col +1 P = self.PrefixM(mat, row, col)res = 2   # 用来存储子正方形矩阵边长的大小,文中要求的得不明确,我这里设置的是边长至少为2, 也就是这个子矩阵中至少有4个元素ans = 0  # 为什么要将ans和res 分开存储,这是因为:如果直接返回 res的话,当没有满足要求的子矩阵的时候,也会返回2,这是不行的for c in range(1, col+1):for r in range(1, row+1):# 当起点为(r, c)时, 最大可能的边长为矩阵【(r, c)- (row-1, col-1) 】的较短边cmax = min(col+1 - c, row+1 - r)for n in range(res, cmax+1):  # 注意这里的边界,实际取值为[res, ..., cmax]S = P[r + n - 1][c + n - 1] - P[r-1][c + n - 1] - P[r + n - 1][c-1] + P[r-1][c-1]if S > threshold:breakif S <= threshold and n >= res:res = nans = nreturn ansdef PrefixM(self, mat, row, col):# 为矩阵mat 扩展一行、一列P = [[0 for i in range(col+1)] for j in range(row+1)]# 这里从(1,1)开始,是为了当出现r-1= -1 和 c-1= -1 的时候直接为0 for r in range(1, row+1):for c in range(1, col+1):# 由于起点不同, P矩阵的(r,c)对应的时mat 矩阵[r-1, c-1]:P[r][c] = mat[r-1][c-1] + P[r - 1][c] + P[r][c - 1] - P[r - 1][c - 1]return P

复杂度分析

由于只要获得了P矩阵就可以快速获得子矩阵的元素和, 加上枚举的优化, 因为这里时间复杂度为O(M*N)

一上午的时间只做了这一个题,我的内心时崩溃的,下午又花了一个多小时写博客,我的内心更崩溃了,但是搞懂了,有些技巧其它地方也可以用,还是要笑着面对。

Leetcode-元素和小于等于阈值的正方形的最大边长(python)相关推荐

  1. LeetCode(1292):元素和小于等于阈值的正方形的最大边长 Maximum Side Length of a Square(Java)

    2020.12.24 LeetCode 从零单刷个人笔记整理(持续更新) github:https://github.com/ChopinXBP/LeetCode-Babel 原地动态规划 + 前缀和 ...

  2. 元素和小于等于阈值的正方形的最大边长(来源:力扣(LeetCode))

    元素和小于等于阈值的正方形的最大边长(来源:力扣(LeetCode)) 给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold.请你返回元素总和小于或等于阈值的正方形区域的最大 ...

  3. 1292. 元素和小于等于阈值的正方形的最大边长-前缀和算法

    1292. 元素和小于等于阈值的正方形的最大边长-前缀和算法 给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold. 请你返回元素总和小于或等于阈值的正方形区域的最大边长:如 ...

  4. LeetCode 1292. 元素和小于等于阈值的正方形的最大边长(DP)

    1. 题目 给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold. 请你返回元素总和小于或等于阈值的正方形区域的最大边长: 如果没有这样的正方形区域,则返回 0 . 示例 1 ...

  5. leetcode1292. 元素和小于等于阈值的正方形的最大边长(二分法+前缀和)

    给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold. 请你返回元素总和小于或等于阈值的正方形区域的最大边长:如果没有这样的正方形区域,则返回 0 . 示例 2: 输入:ma ...

  6. 已知正方形面积求边长c语言,正方形知道面积怎么求边长.

    2019-10-09阅读(206) 长方形的周长=(长+宽)×2正方形的周长=边长×4长方形的面积=长×宽正方形的面积=边长×边长三角形的面积=底×高÷2平行四边形的面积=底×高梯形的面积=(上底+下 ...

  7. 【LeetCode】222. Count Complete Tree Nodes 解题报告(Python)

    [LeetCode]222. Count Complete Tree Nodes 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个 ...

  8. leetcode 221. Maximal Square | 221. 最大正方形(优化的暴力解法+动态规划解法)

    题目 https://leetcode.com/problems/maximal-square/ 题解 方法1:最暴力解 O((m*n)^2) public class Solution {publi ...

  9. 模拟卷Leetcode【普通】2013. 检测正方形

    汇总:模拟卷Leetcode 题解汇总 2013. 检测正方形 给你一个在 X-Y 平面上的点构成的数据流.设计一个满足下述要求的算法: 添加 一个在数据流中的新点到某个数据结构中.可以添加 重复 的 ...

最新文章

  1. MPX2053DP压力传感器简单测量
  2. rabbitmq java集群_RabbitMQ集群整合SpringBoot2.x
  3. C#_获取 SQL服务器列表
  4. opencv函数findcontours_OpenCV系列之轮廓入门 | 二十一
  5. vue require css html,requirejs vue vue.router简单框架
  6. java csv 导入数据库_java – 如何上传CSV文件然后自动将数据插入数据库?
  7. Java笔记12-函数式接口
  8. JavaScript缓存处理代码
  9. 百度离线地图——瓦片地图下载
  10. 大小限制_微信传文件有大小限制?PPT太大怎么传?PPT自带三大压缩功能
  11. outlook连接谷歌企业邮箱(转)
  12. 0017 求正方体的体积与表面积
  13. Rhino学习教程——1.4
  14. 启动springboot报错:程序包org.springframework.boot不存在
  15. android profile 打包_Android 利用 Managed Profile 确保兼容性
  16. App中英文切换简单好用
  17. 简单手机短信发送软件
  18. 新手如何对文件进行简单的上传
  19. 计算机网络并行传输和串行传输,并行传输和串行传输的区别是什么
  20. 聊天记录怎么删除才能防止被恢复

热门文章

  1. 使用代理服务器之后浏览器无法联网的解决办法
  2. 手写板签字php,手写板,签字版
  3. 全球与中国激光光导鼓市场深度分析及发展研究预测报告
  4. 苹果iOS 5限制应用本地存储问题
  5. swift 调用震动
  6. 【Codesys】字节数组转长字节,长字节转字节数组,同点位坐标系位置偏移计算
  7. Excel根据某一列的内容对另一列进行分组汇总
  8. 龙芯 ls2k 保留内存
  9. HTML-网页-3D旋转相册-创意相册
  10. adas记录仪app_路影行车记录仪app