2020/05/08 每日一题

221 最大正方形面积

是一道做过的题目出现在了每日一题,今后的每日一题我尽量把相关的题目都写一遍。

这道题目的思路并不是看到01矩阵就采用暴力的bfs方法,而是可以采用dp的思想。因为正方形具有不错的性质可以采用保存边长的方法,最后计算面积。

  • 核心dp:dp[i][j] = min(dp[i-1][j-1], dp[i][j-1], dp[i-1][j])+1。寻找三个位置的最小值。
class Solution:def maximalSquare(self, matrix: List[List[str]]) -> int:n = len(matrix)if not n:return 0m = len(matrix[0])dp = [[0]*(m+1) for _ in range(n+1)]ans = 0for i in range(1, n+1):for j in range(1, m+1):if matrix[i-1][j-1] == '1':dp[i][j] = min(dp[i-1][j-1], dp[i][j-1], dp[i-1][j])+1ans = max(dp[i][j], ans)return ans*ans

85 最大矩形面积

将问题从正方形变成最大矩形,问题就复杂了一下。
正方形的设计很固定的,我们上一个问题中,给定一个点,计算左上方的大小。但是对于长方形,即使你知道这个点是长方形的右下角,但是也无法确定长方形是躺下还是立起来的。

因此这里采用一种全新的dp思路。给定一个点(i,j)我们首先向上伸展得到最大的高度,然后分别计算出左右伸展可以达到的坐标。这样可以计算以该点伸展开的长方形的大小。

核心在于如何维护左右伸展,我们需要保证在同一列中连续出现1时维护一个最紧的边界。

具体我在代码中进行了注释,这段代码其实用到了状态压缩。

class Solution {public int maximalRectangle(char[][] matrix) {int m = matrix.length;if (m == 0) {return 0;}int n = matrix[0].length;// 往左延申横向可以有多宽int[][] left = new int[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (matrix[i][j] == '1') {left[i][j] = (j == 0 ? 0 : left[i][j - 1]) + 1;}}}int ret = 0;for (int j = 0; j < n; j++) { // 对于每一列,使用基于柱状图的方法int[] up = new int[m];int[] down = new int[m];Deque<Integer> stack = new LinkedList<Integer>();// 更新上界for (int i = 0; i < m; i++) {while (!stack.isEmpty() && left[stack.peek()][j] >= left[i][j]) {stack.pop();}// 小于当前元素的最大的。up[i] = stack.isEmpty() ? -1 : stack.peek();stack.push(i);}stack.clear();// 更新下届for (int i = m - 1; i >= 0; i--) {while (!stack.isEmpty() && left[stack.peek()][j] >= left[i][j]) {stack.pop();}// 小于当前元素最大的down[i] = stack.isEmpty() ? m : stack.peek();stack.push(i);}// 计算当前列的每一行for (int i = 0; i < m; i++) {int height = down[i] - up[i] - 1;int area = height * left[i][j]; // 以第i行作为最高点,上下延申的矩形面积 从左侧0到当前的j列。ret = Math.max(ret, area);}}return ret;}
}
class Solution:def maximalSquare(self, matrix: List[List[str]]) -> int:if not matrix:return 0n = len(matrix)m = len(matrix[0])# 构建三个dpleft = [0]*mright = [m]*mheight = [0]*mans = 0for i in range(n):# 在新的一行开始迭代时要初始化cur_left, cur_right = 0, m  # 注意这里设置右端为m,为了保证左右相减得到的正好等于宽度# 可达左边界的坐标for j in range(m):if matrix[i][j] == '1':left[j] = max(left[j], cur_left)else:left[j] = 0  ## 保证下行在比较该列时候,不会遇到麻烦cur_left = j+1# 可达上边界的距离for j in range(m):if matrix[i][j] == "1":height[j] += 1else:height[j] = 0# 可达右边界的坐标    for j in range(m-1, -1, -1):if matrix[i][j] == '1':right[j] = min(right[j], cur_right)else:right[j] = m ## 保证下行在比较该列时候,不会遇到麻烦cur_right = jfor j in range(m):ans = max(ans, height[j]*(right[j]+-left[j]))return ans

上边界的更新比较简单,重点看代码中左右边界的更新策略。

在同一行搜索中,左边界从左向右,右边界从右向左搜索每次遇到0就更新当前行的边界cur_X,并且将这个位置的数值设为最大边界(0或者m)为了方便下一行在计算到该位置时不受上一行的影响。

84 柱形图中最大面积

换成了柱形图,同样类似的题目,但是还是存在一种新的思路的,这一类接雨水,等等题目,特点都是需要寻找下一个左右更大或者更小的数值。因此单调栈的思路很巧妙。

题目的思路在于维护一个单增的单调栈,在每次出栈时候进行计算,计算方法是当前左边i-1 - 出栈元素前一个元素index * 出栈坐标对应的值

细节:考虑清楚如何处理第一个和最后一个元素,第一个元素弹出时,是没有前驱的。因为我们需要在数组头补0。最后一个加入队列之后,循环就会结束,并且我们是在每次弹栈时候进行计算,因此我们需要在数组尾部补0

class Solution:def largestRectangleArea(self, heights: List[int]) -> int:queue = []# 注意这里的前驱补0和后继补0heights = [0]+heights+[0]n  = len(heights)ans = 0for i in range(n):while queue and heights[queue[-1]]>heights[i]:temp = queue.pop()ans = max(ans, (i-1-queue[-1])*heights[temp])queue.append(i)return ans

复杂度O(n)O(n)O(n)实际上每个进栈的元素最后都被弹出计算了一遍。

为什么不在元素加入栈时候计算呢?
答:这样会增加复杂度,因为我们需要计算添加这个元素之后,栈前面的所有元素都可以多了一个单位进行累加。就不如在弹出时候计算简便。

【每日一题】最大正方形面积——进阶,矩形面积相关推荐

  1. 【每日一题】042 基因牛 三角形面积

    题目详情: 题目描述 本题为代码补全填空题,请将题目中给出的源代码补全,并复制到右侧代码框中,选择对应的编译语言(C/Java)后进行提交.若题目中给出的源代码语言不唯一,则只需选择其一进行补全提交即 ...

  2. HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)

    链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...

  3. 题目 1471:【蓝桥杯】【入门题】【基础练习VIP】矩形面积交

    题目 1471:矩形面积交 蓝桥杯刷题群已成立,微信后台回复[蓝桥杯],即可进入. 如果加入了之前的社群不需要重复加入. 时间限制: 1Sec 内存限制: 128MB 1. 题目描述 平面上有两个矩形 ...

  4. 01矩阵最大正方形面积、01矩阵最大矩形面积、直方图最大矩形面积

    01矩阵最大正方形面积 题意:给定一个矩阵,其中的元素为0或者1,要求找出其中元素全为1的面积最大的正方形. 题解:动态规划:对每个元素,把以其为右下角,元素全为1的正方形的最长边长记录下来.如果以元 ...

  5. 每日一题-正方形的判定

    title: 每日一题–正方形的判定 date: 2019-11-17 09:32:04 tags: 算法 每日一题 1.2018三大校赛题B-正方形的判断 (10分) 题目内容: 给定四个点的坐标, ...

  6. 王者服务器维护结束2020331,S19荣耀进阶战令的星元部件是哪一位英雄的 王者荣耀2020年3月31日每日一题答案 - 找游戏手游网...

    版本:v1.52.1.37 类型:MOBA跑酷大小:1.98 GB评分:9.2 标签: moba 腾讯游戏 塔防 竞技游戏 角色扮演 联机对战 立即下载 S19荣耀进阶战令的星元部件是哪一位英雄的?这 ...

  7. Java利用继承和多态来求矩形、正方形和圆形的面积与周长

    题目 Java利用继承和多态来求矩形.正方形和圆形的面积与周长 import static java.lang.Math.PI;/*** @Author Ziph* @date 2020/2/20* ...

  8. Codeforces Round #694 (Div. 1 + Div2)(A ~ H,8题全,超高质量题解)【每日亿题】2021/2/1、2/2

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 [每日亿题]Codeforces Round #694 (Div. 1 + Div2)(A ~ ...

  9. 【每日一题】7月15日题目精讲—生日快乐

    [每日一题]7月15日题目精讲-生日快乐 [SCOI2009]生日快乐 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO For ...

最新文章

  1. linux使用grep获取两个文件相同的行或不同的行
  2. 请求数据分析 xpath语法 与lxml库
  3. HDU2191——悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
  4. 直接调用内置数据源连接对话框(C#/VB.NET2005源码)
  5. 使用可重启AD DS 整理活动目录数据库
  6. android sdk 最新国内镜像下载,【Android SDK Manager】SDk国内镜像下载地址
  7. ie浏览器css怎么调,IE浏览器下的CSS问题小结
  8. CAD曲线快捷键是什么?CAD画曲线教程
  9. qcc烧录工具/qcc全系列量产单个烧录工具烧录软件qcc3020/3040/5124/5126/5144
  10. 如何用计算机函数来求加权总分,Excel小技巧-使用函数「SUMPRODUCT」计算加权后的总和及平均值...
  11. 《灵飞经5·龙生九子》 第二十二章 河咸海淡(上)
  12. springboot整合任务安全
  13. Java语言开发在线购物推荐网 购物商城推荐系统 基于用户、物品的协同过滤推荐算法 SSM(Spring+SpringMVC+Mybatis)开发框架 大数据、人工智能、机器学习项目开发
  14. python中文编辑_python用Tkinter做自己的中文代码编辑器
  15. 【用过的抢票软件汇总】
  16. Tensorflow 神经网络模型架构
  17. Python 中 int 用法详解
  18. c语言中的return 0有什么用?
  19. 笔记本连接双显示屏相关问题
  20. visibility:属性

热门文章

  1. Dagger2使用解析
  2. 注解@Primary
  3. 使用ROS开源代码和激光雷达进行小车的定位导航
  4. Linux防火墙的配置
  5. Git git config 配置使用
  6. HTML5篮球弹跳运动规律,打篮球怎么练弹跳力 弹跳力怎么训练
  7. 仲恺计算机二级c语言,2009年下半年(第30次)全国计算机等级考试(NCRE)广东考区报考简章...
  8. 云之道知识付费3.1.1【最新开源】全插件,独立版
  9. 微型计算机aspire1600x,Acer 1600X小型机拆解
  10. ubuntu命令行查看dns_Ubuntu命令行网络配置