[ 一刷完结撒花!! ] Day50 力扣单调栈 : 503.下一个更大元素II |42. 接雨水 | 84.柱状图中最大的矩形

Day50 力扣单调栈 : 503.下一个更大元素II |42. 接雨水 | 84.柱状图中最大的矩形

  • 503.下一个更大元素II
    • 第一印象
    • 看完题解的思路
    • 实现中的困难
    • 感悟
    • 代码
  • 42. 接雨水
    • 第一印象
    • 看完题解的思路
      • 暴力解法
      • 单调栈解法
    • 实现中的困难
    • 感悟
    • 代码
  • 84.柱状图中最大的矩形
    • 第一印象
    • 看完题解的思路
    • 感悟
    • 代码

503.下一个更大元素II

这道题和 739. 每日温度 几乎如出一辙,可以自己尝试做一做

https://programmercarl.com/0503.%E4%B8%8B%E4%B8%80%E4%B8%AA%E6%9B%B4%E5%A4%A7%E5%85%83%E7%B4%A0II.html

第一印象

好, 那我就自己试试.

做出来了.

之前的单调栈题目就是遍历一遍数组, 找这一遍里右面最大的那个.

这道题说是循环数组, 其实也就是找两圈这个数组.

比如 5 2 3. 5是比3大的, 第一圈里只能找出3比2大, 第二圈才能找到5比3大.

有两个方式我觉得, 一个是找两圈数组, 也是我下面代码写的.

或者直接改造这个数组, 变成自己的两倍大小, 元素是自己的两遍, 比如5 2 3 5 2 3.

我自己写的代码,请看vcr:

class Solution {public int[] nextGreaterElements(int[] nums) {int[] result = new int[nums.length];Deque<Integer> stack = new LinkedList<>();int loop = 1;Arrays.fill(result, -1);stack.push(0);for (int i = 1; i < nums.length; i++) {if (nums[i] <= nums[stack.peek()]) {stack.push(i);} else {while (!stack.isEmpty() && nums[i] > nums[stack.peek()]) {//弹出栈顶元素,是下标int index = stack.pop();//记录结果result[index] = nums[i];}stack.push(i);}if (loop == 1 && i == nums.length - 1) {//因为循环结束 i++, 而第二圈应该从 i=0 开始.i = -1;loop--;continue;}}return result;}
}

看完题解的思路

确实, 就是我上面说的两种方式, 但是扩大数组的复杂度就是O(n)了

而走两圈的方式, 卡哥比我做的要聪明一些, 用 % .

其实我也想到了, 就是感觉容易混乱在数学里.

for(int i = 0; i < 2*size; i++) {while(!st.empty() && nums[i % size] > nums[st.peek()]) {result[st.peek()] = nums[i % size];//更新resultst.pop();//弹出栈顶}st.push(i % size);
}

实现中的困难

在我的代码里

if (loop == 1 && i == nums.length - 1) {//因为循环结束 i++, 而第二圈应该从 i=0 开始.i = -1;loop--;continue;
}

走两圈的逻辑, 应该让 i = -1 ,而不是 i = 0

因为for循环结束之后会有 i++ .

感悟

虽然麻烦了点, 但我还是做对了

代码

上面给出了.

42. 接雨水

接雨水这道题目是 面试中特别高频的一道题,也是单调栈 应用的题目,大家好好做做。

建议是掌握 双指针 和单调栈,因为在面试中 写出单调栈可能 有点难度,但双指针思路更直接一些。

在时间紧张的情况有,能写出双指针法也是不错的,然后可以和面试官在慢慢讨论如何优化。
https://programmercarl.com/0042.%E6%8E%A5%E9%9B%A8%E6%B0%B4.html

第一印象

想了一下, 感觉情况比较多

  • 两边都比自己高, 选小的那个 - 自己 = 水
  • 两边有一边比自己高, ??? 这种情况咋办呢
  • 两边都没自己高, 没有水

看题解!

看完题解的思路

暴力解法

找到右边第一个比自己大的, 左面第一个比自己大的. 就能算出来自己这里有多少水. 硬暴力去算.

单调栈解法

对于单调栈, 前面的题目已经会了找右边更大的(栈元素递增), 右边更小的(栈元素递减).

那怎么找左边更大的呢? 我第一反应是逆序遍历数组.

可以, 但有更好的方式. 这道题就是找到三个柱子, 左边更大+自己+右边更大

自己就是栈顶元素, 拿来的元素 i 可能是右边更大的(不更大就push入栈了), 那左边更大的在哪?

其实就是栈顶下面的那个元素, 如图:

因为栈里是递增的, 我自己下面那个就是 我左面第一个更大的呀

太tm巧妙了!!!
在这里插入图片描述

看完了, 会了

重要的是, 这道题是横向的求雨水面积, 我一直想的是 纵向的求雨水面积.

我听完题解还是觉得纵向的求没有错

但是细看

在这里插入图片描述

这个地方左面第一个更高和右边第一个更高最小的是 1

自己是 0

那么纵向雨水就是 1 , 算不到红色方块那里的

实现中的困难

思路清晰就不难实现

感悟

确实比较难

一个是纵向和横向计算容易糊涂

我也觉得横向计算的话, 下图的两个地方不会重复吗?

在这里插入图片描述

不会的

因为第二个 1 拿来的时候, 就比 0大了, 就会进行一次计算.

算出雨水量 1, 并把 0 pop掉, 第二个 1 push进去

拿来 3 的时候, 比栈顶的第二个 1 更大, 就会进行一次计算.

但是栈顶下面的元素就是第一个 1 , 在计算高度的时候, 取第一个 1 和 3 更小的那个 再减去栈顶的第二个 1 . 高度就是0 , 就白计算了.

然后第二个 1 pop

这个时候栈顶是第一个 1 , 栈顶下面的元素是 2 , 就会进行一次计算.

算出 高度 1 ,宽度 3, 雨水量 3.

然后pop掉第一个 1, 3 比栈顶的 2 还要大. 但是呢, pop 2 之后, 栈就空了, 就不会计算, 只是 pop 了2.

最后 3 push进栈, 再去算后面的元素.

顿悟 咯~~~~~~~~~~~~~

代码

class Solution {public int trap(int[] height) {int result = 0;Deque<Integer> stack = new LinkedList<>();stack.push(0);for (int i = 1; i < height.length; i++) {if (height[i] < height[stack.peek()]) {stack.push(i);} else if (height[i] == height[stack.peek()]) {stack.pop();stack.push(i);} else {while (!stack.isEmpty() && height[i] > height[stack.peek()]) {int curIndex = stack.pop();int cur = height[curIndex];//如果还有左边的话if (!stack.isEmpty()) {int min = Math.min(height[i], height[stack.peek()]);//求高度int h = min - cur;int w = i - stack.peek() - 1;//我纵向的求int rain = w * h;result += rain;}}stack.push(i);}}return result;}
}

84.柱状图中最大的矩形

https://programmercarl.com/0084.%E6%9F%B1%E7%8A%B6%E5%9B%BE%E4%B8%AD%E6%9C%80%E5%A4%A7%E7%9A%84%E7%9F%A9%E5%BD%A2.html

今天是训练营最后一天,恭喜坚持两个月的录友们,接下来可以写一篇自己
代码随想录一刷的总结。好好回顾一下,这两个月自己的博客内容,以及自己的收获。

第一印象

我也觉得是要找左右两边第一个更小的

题解也是这么写的.

但是为啥呢

我只是有一种直觉, 它不像接雨水那样比较直观.

看完题解的思路

我明白了, 拿题里的例子说明一下

在这里插入图片描述

比如拿到元素 1 , 向左找第一个更小, 没有. 向右找第一个更小, 没有.

所以 1 的高度, 贯穿整个数组.

比如拿到 5, 向左找第一个更小是 1 . 向右找第一个更小, 是2.

那么 5 的高度就是从 1 贯穿到 2, 宽度其实就是 2 的下标 - 1 的下标 - 1.

这就是为什么要向左向右找第一个更小的原因.

也就是看现在这个元素(是高度)能贯穿多长(宽度).

然后这道题还有个处理技巧, 给数组扩容, 头和尾都加上高度 0 .

这样就方便算头和尾的元素的面积. 而且还能算出那个 最矮 的 1 的面积. 如图

在这里插入图片描述

但这里又会产生一个问题

对于相等的情况我自己写的时候的处理是, 什么都不做

if (heights[i] > heights[stack.peek()]) {stack.push(i);
} else if (heights[i] == heights[stack.peek()]) {//不处理, 相同的话先放进来的元素会让面积更大
} else {

比如 1 4 4 3.

肯定是第一个 4 算出的面积更大, 第二个 4 就是 4*1, 第一个 4 是 4 * 2.

所以遇到相同元素, 什么都不做就行了.

但是由于头加了 0 , 如果第一个高度还是 0的话就会出现错误.

在这里插入图片描述
扩容之后的数组是 0 0 9 0

因为相同元素什么都不干, 所以第二个 0 不会压入栈

在这里插入图片描述

这样计算 这个 9 的时候, 宽度就是 2 了. 就错了!!!

所以不能让相同元素什么都不干.

而是像接雨水一样, pop 在push 可以, 只push 也可以

还拿 1 4 4 3 的例子

pop 再 push, 栈顶就是第二个 4 , 下面是 1 . 拿到元素 3 的时候, 计算的宽度也是 3 - 0 - 1 = 2. 算的是到 1 到 3 的宽度. 是大的那个.

只push呢, 栈顶是第二个4 然后第一个4, 然后是 1 . 就是先算一个小的面积, 再算大的.

都是对的, 就是什么都不做不行.

感悟

这题也挺奇妙, 但是栈里递增递减不是什么难的.

主要就是头和尾 + 0 的小技巧

代码

class Solution {public int largestRectangleArea(int[] heights) {int maxArea = 0;Deque<Integer> stack = new LinkedList<>();// 数组扩容,在头和尾各加入一个元素int [] newHeights = new int[heights.length + 2];newHeights[0] = 0;newHeights[newHeights.length - 1] = 0;for (int index = 0; index < heights.length; index++){newHeights[index + 1] = heights[index];}heights = newHeights;stack.push(0);for (int i = 1; i < heights.length; i++) {if (heights[i] > heights[stack.peek()]) {stack.push(i);} else if (heights[i] == heights[stack.peek()]) {stack.pop();stack.push(i);} else {while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) {int curIndex = stack.pop();int cur = heights[curIndex];if (!stack.isEmpty()) {int weight = i - stack.peek() - 1;int area = cur * weight;System.out.println(area + "=" + cur + "*" + weight);maxArea = Math.max(maxArea, area);}    }stack.push(i);}}return maxArea;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/193979.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OceanBase:Zone管理

OceanBase 集群由若干个 Zone 组成。从物理层面来讲&#xff0c;一个 Zone 通常是一个独立的物理部署单元&#xff0c;可以是一个数据中心&#xff08;IDC&#xff09;或者云上的一个 Zone&#xff08;可用区&#xff09;&#xff0c;也可以是一个单独的机架&#xff08;Rack&a…

WIFI版本云音响设置教程腾讯云平台版本

文章目录 WIFI版本云音响设置教程腾讯云平台版本一、申请设备三元素1.腾讯云物联网平台2.创建产品3.设置产品参数4.添加设备5.获取三元素 二、设置设备三元素1.打开MQTTConfigTools2.计算MQTT参数3.使用windows电脑的WIFI连接到设备热点4.设置参数 三、腾讯云物联网套件协议使用…

开源更安全? yum源配置/rpm 什么是SSH?

文章目录 1.开放源码有利于系统安全2.yum源配置&#xff0c;这一篇就够了&#xff01;(包括本地&#xff0c;网络&#xff0c;本地共享yum源)3.rpm包是什么4.SSH是什么意思&#xff1f;有什么功能&#xff1f; 1.开放源码有利于系统安全 开放源码有利于系统安全 2.yum源配置…

Windows网络「SSL错误问题」及解决方案

文章目录 问题方案 问题 当我们使用了神秘力量加持网络后&#xff0c;可能会和国内的镜像源网站的之间发生冲突&#xff0c;典型的有 Python 从网络中安装包&#xff0c;如执行 pip install pingouin 时&#xff0c;受网络影响导致无法完成安装的情况&#xff1a; pip config…

Sql Server 2017主从配置之:发布订阅

使用发布订阅模式搭建Sql Server 2017主从同步&#xff0c;类似事件通知机制&#xff0c;基本可以做到准实时同步&#xff0c;可以同时做到一对多的数据同步。 不过发布订阅模式&#xff0c;只能同时数据&#xff0c;不能同步表结构。在创建发布的时候&#xff0c;需要选择需要…

人工智能-深度学习之序列模型

想象一下有人正在看网飞&#xff08;Netflix&#xff0c;一个国外的视频网站&#xff09;上的电影。 一名忠实的用户会对每一部电影都给出评价&#xff0c; 毕竟一部好电影需要更多的支持和认可。 然而事实证明&#xff0c;事情并不那么简单。 随着时间的推移&#xff0c;人们对…

将word中的表格无变形的弄进excel中

在上篇文章中记录了将excel表拷贝到word中来&#xff1a; 记录将excel表无变形的弄进word里面来-CSDN博客 本篇记录&#xff1a;将word中的表格无变形的弄进excel中。 1.按F12&#xff0c;“另存为...”&#xff0c;保存类型&#xff1a;“单个文件页面”&#xff0c;保存。…

Linux进程间通信之匿名管道

文章目录 为什么要有进程间通信pipe函数共享管道原理管道特点管道的应用场景&#xff08;进程池&#xff09;ProcessPool.ccTask.hpp 为什么要有进程间通信 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程 资源共享&#xff1a;多个进程之间共享同样的资源。 通…

Windows10 MYSQL Installer 安装(mysql-installer-community-5.7.19.0.msi)

分类 编程技术 1.进入官网找到自己所需的安装包&#xff1a;https://dev.mysql.com/ &#xff0c;路径&#xff1a;DOWNLOAD-->MYSQL Community Edition(GRL)-->MYSQL on Windows (Installer & Tool) 或直接点击 MySQL :: Download MySQL Installer 查看最新版本。…

毅速丨3D打印透气钢正在被各行业广泛应用

随着制造技术的发展&#xff0c;企业对生产效率和产品品质的进一步提高&#xff0c;3D打印透气钢已逐渐在各行业中广泛应用。传统的透气钢制造方法&#xff0c;如粉末冶金和扩散焊&#xff0c;通常只能加工出透气钢的嵌块&#xff0c;使用时需要进行镶嵌&#xff0c;存在强度不…

游戏数据分析必知必会

游戏的分类 按端分类&#xff1a;端游&#xff08;steam&#xff09;&#xff0c;页游&#xff08;4399&#xff09;&#xff0c;手游&#xff08;手机&#xff0c;pad&#xff09;按盈利模式分类&#xff1a;付费游戏&#xff08;一次买断&#xff0c;后续购买其它剧情或者包…

MySQL 教程 1.2

上期教程网友笔记整理 MySQL 重置密码 如果你忘记 MySQL 密码&#xff0c;可以通过修改 my.cnf 文件添加 skip-grant-tables 来重置密码&#xff0c;步骤如下&#xff1a; 1、打开 my.cnf 配置文件&#xff0c;找到 [mysqld] &#xff0c;然后在该行下面添加以下参数&#x…