Leetcode-元素和小于等于阈值的正方形的最大边长(python)
题目
给你一个大小为 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)相关推荐
- LeetCode(1292):元素和小于等于阈值的正方形的最大边长 Maximum Side Length of a Square(Java)
2020.12.24 LeetCode 从零单刷个人笔记整理(持续更新) github:https://github.com/ChopinXBP/LeetCode-Babel 原地动态规划 + 前缀和 ...
- 元素和小于等于阈值的正方形的最大边长(来源:力扣(LeetCode))
元素和小于等于阈值的正方形的最大边长(来源:力扣(LeetCode)) 给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold.请你返回元素总和小于或等于阈值的正方形区域的最大 ...
- 1292. 元素和小于等于阈值的正方形的最大边长-前缀和算法
1292. 元素和小于等于阈值的正方形的最大边长-前缀和算法 给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold. 请你返回元素总和小于或等于阈值的正方形区域的最大边长:如 ...
- LeetCode 1292. 元素和小于等于阈值的正方形的最大边长(DP)
1. 题目 给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold. 请你返回元素总和小于或等于阈值的正方形区域的最大边长: 如果没有这样的正方形区域,则返回 0 . 示例 1 ...
- leetcode1292. 元素和小于等于阈值的正方形的最大边长(二分法+前缀和)
给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold. 请你返回元素总和小于或等于阈值的正方形区域的最大边长:如果没有这样的正方形区域,则返回 0 . 示例 2: 输入:ma ...
- 已知正方形面积求边长c语言,正方形知道面积怎么求边长.
2019-10-09阅读(206) 长方形的周长=(长+宽)×2正方形的周长=边长×4长方形的面积=长×宽正方形的面积=边长×边长三角形的面积=底×高÷2平行四边形的面积=底×高梯形的面积=(上底+下 ...
- 【LeetCode】222. Count Complete Tree Nodes 解题报告(Python)
[LeetCode]222. Count Complete Tree Nodes 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个 ...
- leetcode 221. Maximal Square | 221. 最大正方形(优化的暴力解法+动态规划解法)
题目 https://leetcode.com/problems/maximal-square/ 题解 方法1:最暴力解 O((m*n)^2) public class Solution {publi ...
- 模拟卷Leetcode【普通】2013. 检测正方形
汇总:模拟卷Leetcode 题解汇总 2013. 检测正方形 给你一个在 X-Y 平面上的点构成的数据流.设计一个满足下述要求的算法: 添加 一个在数据流中的新点到某个数据结构中.可以添加 重复 的 ...
最新文章
- MPX2053DP压力传感器简单测量
- rabbitmq java集群_RabbitMQ集群整合SpringBoot2.x
- C#_获取 SQL服务器列表
- opencv函数findcontours_OpenCV系列之轮廓入门 | 二十一
- vue require css html,requirejs vue vue.router简单框架
- java csv 导入数据库_java – 如何上传CSV文件然后自动将数据插入数据库?
- Java笔记12-函数式接口
- JavaScript缓存处理代码
- 百度离线地图——瓦片地图下载
- 大小限制_微信传文件有大小限制?PPT太大怎么传?PPT自带三大压缩功能
- outlook连接谷歌企业邮箱(转)
- 0017 求正方体的体积与表面积
- Rhino学习教程——1.4
- 启动springboot报错:程序包org.springframework.boot不存在
- android profile 打包_Android 利用 Managed Profile 确保兼容性
- App中英文切换简单好用
- 简单手机短信发送软件
- 新手如何对文件进行简单的上传
- 计算机网络并行传输和串行传输,并行传输和串行传输的区别是什么
- 聊天记录怎么删除才能防止被恢复