day58 单调栈

news/2024/5/15 0:37:46/文章来源:https://blog.csdn.net/weixin_42410511/article/details/131894402

单调栈

使用场景:通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置

本质:空间换时间

三个判断条件
当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况

739. 每日温度

class Solution {
public:vector<int> dailyTemperatures(vector<int>& temperatures) {stack<int>s;vector<int>result(temperatures.size(), 0);s.push(0);int index = 1;while(index < temperatures.size()){while(!s.empty() && temperatures[s.top()] < temperatures[index]){int temp = s.top();s.pop();result[temp] = index - temp;}s.push(index);index++;}return result;}
};

496. 下一个更大元素 I
题目: 给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。
请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。

思路 : num2作单调栈找下一个大的值,弹出时,判断是否在num1中出现过,如果出现则进行赋值,链接使用unordered_map

class Solution {
public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {vector<int>result(nums1.size(), -1);unordered_map<int, int>m;stack<int>s;for(int i=0; i<nums1.size();i++){m[nums1[i]] = i;  }s.push(0);int index = 1;while(index < nums2.size()){while(!s.empty() && nums2[s.top()] < nums2[index]){ //弹出时判断if(m.find(nums2[s.top()]) != m.end()){result[m[nums2[s.top()]]] = nums2[index];}s.pop();}s.push(index);index++;}return result;}
};

503. 下一个更大元素 II

题目:循环数组

简单版: 两个数组拼接在一起,然后使用单调栈求下一个最大值

class Solution {
public:vector<int> nextGreaterElements(vector<int>& nums) {int n = nums.size();vector<int>result(n , -1);for(int i=0; i<n; i++) nums.push_back(nums[i]);stack<int>s;s.push(0);for(int i=1; i<nums.size(); i++){while(!s.empty() && nums[s.top()] < nums[i]){if(s.top()<n){result[s.top()] = nums[i];}s.pop();}s.push(i);}return result;}
};

改进版: 不扩充nums,而是在遍历的过程中模拟走了两边nums

class Solution {
public:vector<int> nextGreaterElements(vector<int>& nums) {int n = nums.size();vector<int>result(n , -1);stack<int>s;s.push(0);for(int i=1; i<n*2; i++){while(!s.empty() && nums[s.top()%n] < nums[i%n]){if(s.top()<n){result[s.top()] = nums[i%n];}s.pop();}s.push(i);}return result;}
};

42. 接雨水

在这里插入图片描述

  1. 暴力
    思路:如果按照列来计算的话,宽度一定是1了,我们再把每一列的雨水的高度求出来就可以了
    每一列雨水的高度,取决于,该列左侧最高的柱子和右侧最高的柱子中最矮的那个柱子的高度。

问题:复杂度为O(n^2) 超时

class Solution {
public:int trap(vector<int>& height) {int sum = 0;for(int i=1; i<height.size()-1; i++){int left = 0;int right = 0;for(int j=i; j>=0; j--){left = max(left, height[j]);}for(int j=i; j<height.size(); j++){right = max(right, height[j]);}sum += min(left, right) - height[i];}return sum;}
};

2.双指针改进暴力 空间换时间 提前将左右最高高度算出来

class Solution {
public:int trap(vector<int>& height) {int sum = 0;vector<int>left(height.size(), 0);vector<int>right(height.size(), 0);int m_left = height[0];int m_right = height[height.size()-1];for(int i=0; i<height.size(); i++){m_left = max(m_left, height[i]);left[i] = m_left;}for(int i=height.size()-1; i>=0; i--){m_right = max(m_right, height[i]);right[i] = m_right;}for(int i=1; i<height.size()-1; i++){sum += min(left[i], right[i]) - height[i];}return sum;}
};
  1. 双指针
    在这里插入图片描述
    思路:
    单调栈是按照行方向来计算雨水
    栈顶和栈顶的下一个元素以及要入栈的元素,三个元素来接水
    雨水高度是 min(凹槽左边高度, 凹槽右边高度) - 凹槽底部高度
    水的宽度是 凹槽右边的下标 - 凹槽左边的下标 - 1
class Solution {
public:int trap(vector<int>& height) {stack<int>s;int sum = 0;s.push(0);for(int i=1; i<height.size(); i++){while(!s.empty() && height[s.top()] < height[i]){          int cur = s.top();s.pop();if(!s.empty()){  //来避免 栈内[2] 元素3 村水量 0 只要弹出就可以了int h =  min(height[i], height[s.top()]) - height[cur]; sum += h * (i-s.top()-1);}}s.push(i); }return sum;}
};

84. 柱状图中最大的矩形
题目给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。
在这里插入图片描述
主体思路:
每一个位置能达到的最大面积取决于它左右两侧小于它的高度位置。
int w = right-left - 1;
int h = heights[i];
sum = max(sum, w*h);

暴力超时

class Solution {
public:int largestRectangleArea(vector<int>& heights) {int sum = 0;for(int i=0; i<heights.size(); i++){int left = i;int right = i;while(left >= 0){if(heights[left] < heights[i]) break;left--;}while(right < heights.size()){if(heights[right] < heights[i]) break;right++;}int w = right-left - 1;int h = heights[i];sum = max(sum, w*h);}return sum;}
};

双指针优化,空间换时间,提前记录左右两侧的位置信息没有数组保存时,需要一个一个跳进行比较。有数组后,那么可以利用之前的比较信息进行跳着比较。
heights[left] >= heights[i]) 时
直接跳到 left[left]指向的位置
注意
left是往左跳 则遍历顺序从左到右
right 向右跳,则右边的先算,遍历顺序从右向左

class Solution {
public:int largestRectangleArea(vector<int>& heights) {int n = heights.size();vector<int>left(n, -1);vector<int>right(n, n);for(int i=0; i<n; i++){int l = i-1;while(l>=0 && (heights[l] >= heights[i])) l = left[l];left[i] = l; }for(int i=n-1; i>=0; i--){int r = i+1;while(r < n && (heights[r] >= heights[i])) r = right[r];right[i] =r;}int sum=0; for(int i=0; i<n; i++){sum = max(sum, heights[i] *(right[i]-left[i]-1));}return sum;}
};

单调栈:目的找到左右两侧第一个比它小的元素
栈内元素从小到大,
在这里插入图片描述
当前元素小于栈顶元素时, 当前元素就是右边界,栈顶元素的下一个元素就是左边界, w = right - left - 1 h = height[s.top()] sum = max(sum, h*w)
注意两种情况

  1. 2 3 4 5 递增序列没有机会弹出 所以在最后面加入一个0 —> 2 3 4 5 0
  2. 8 7 6 5 第一个元素没有左边界 所以在最前面加入一个0 —> 0 8 7 6 5
class Solution {
public:int largestRectangleArea(vector<int>& heights) {heights.push_back(0);heights.insert(heights.begin(), 0);int n = heights.size();stack<int>s;s.push(0);int sum = 0;for(int i=1; i<n; i++){if(heights[i] > heights[s.top()]){s.push(i);}else if(heights[i] == heights[s.top()]){s.pop();s.push(i);}else{while(!s.empty() && (heights[i] < heights[s.top()])){int mid = s.top();s.pop();if(!s.empty()){int left = s.top();int w = i-left-1;int h = heights[mid];sum = max(sum, w*h);}}s.push(i);}}return sum;}
};

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

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

相关文章

网络安全学习笔记——burp和SqlMap的tips

一、Burp 爆破 1、Burp爆账号密码 burp爆破的前提条件——该网站账号密码没有进行加密而是明文&#xff0c;且验证码可以重复使用&#xff0c;如下图数据包中直接显示账号与密码且验证码不需要重复提交&#xff08;此处需要自己使用burp进行测试&#xff09; 1、进入burp&am…

树莓派通过天线+gps获取经纬度并调用高德地图api在地图上标点

完整项目为《基于机器视觉的行人和路面缺陷检测及其边缘设备部署》 完整功能视频演示地址&#xff1a;本科最后的课设&#xff1a;“车载系统的辅助系统——基于机器视觉的行人和路面缺陷检测”完结撒花*罒▽罒*_哔哩哔哩_bilibili 该博客介绍的功能为&#xff1a; 1&#xff1…

实例讲解:通过三个案例搞懂tcp的那些冷门知识

最近在做数据库相关的事情&#xff0c;碰到了很多TCP相关的问题&#xff0c;新的场景新的挑战&#xff0c;有很多之前并没有掌握透彻的点&#xff0c;大大开了一把眼界&#xff0c;选了几个案例分享一下。 案例一&#xff1a;TCP中并不是所有的RST都有效 背景知识 在TCP协议…

Selenium-用这个框架自动化任何你想做的事情!

Chrome DevTools 简介 Chrome DevTools 是一组直接内置在基于 Chromium 的浏览器&#xff08;如 Chrome、Opera 和 Microsoft Edge&#xff09;中的工具&#xff0c;用于帮助开发人员调试和研究网站。 借助 Chrome DevTools&#xff0c;开发人员可以更深入地访问网站&#xf…

JPEG有损图像压缩编码器(附源码)

概述 一个基本由自己实现的JPEG有损图像压缩编码器&#xff0c;基于JFIF&#xff08;JPEG文件交换格式&#xff09;标准&#xff1a; 色彩空间转换&#xff08;RGB to YUV&#xff09;色度抽样&#xff08;采样因子4:2:0&#xff09;MCU分块&#xff08;16x16的最小编码单元&…

开放麒麟1.0发布一个月后,到底怎么样?另一款操作系统引发热议

具有里程碑意义 7月5日&#xff0c;国产首个开源桌面操作系统“开放麒麟1.0”正式发布。 标志着我国拥有了操作系统组件自主选型、操作系统独立构建的能力&#xff0c;填补了我国在这一领域的空白。 举国欢庆&#xff0c;算的上是里程碑意义了&#xff01; 发布后用着如何&a…

【Python】PySpark 数据计算 ② ( RDD#flatMap 方法 | RDD#flatMap 语法 | 代码示例 )

文章目录 一、RDD#flatMap 方法1、RDD#flatMap 方法引入2、解除嵌套3、RDD#flatMap 语法说明 二、代码示例 - RDD#flatMap 方法 一、RDD#flatMap 方法 1、RDD#flatMap 方法引入 RDD#map 方法 可以 将 RDD 中的数据元素 逐个进行处理 , 处理的逻辑 需要用外部 通过 参数传入 map…

深入理解 SQL:从基本查询到高级聚合

目录 背景理论知识示例1211. 查询结果的质量和占比&#xff08;Round group by&#xff09;1204. 最后一个能进入巴士的人 &#xff08;Having limit order by&#xff09;1193. 每月交易 I&#xff08;if group by&#xff09;1179. 重新格式化部门表1174. 即时食物配送 II&am…

链表刷题常用技巧——快慢指针

强大&#xff0c;不动如山的强大&#xff0c;不会输给自己的真正的强大。 往期回顾&#xff1a; 数据结构——单链表 单链表力扣刷题 文章目录 经典例题&#xff1a;链表的中间结点 题目分析及双指针思路引入 双指针图解 leetcode 核心代码 判断环形链表——快慢指针…

基于SSM+JSP+LayUI的校园任务帮管理系统

校园帮项目 校园即时服务平台 用户角色 管理员 功能 登录、公告管理&#xff08;发布公告、停用公告&#xff09;、任务管理&#xff08;下架任务、删除任务&#xff09;、用户管理&#xff08;用户充值、限制用户&#xff09;、修改密码 用户角色 用户 功能 注册、登录…

【Linux进程篇】进程概念(1)

【Linux进程篇】进程概念&#xff08;1&#xff09; 目录 【Linux进程篇】进程概念&#xff08;1&#xff09;进程基本概念描述进程-PCBtask_struct-PCB的一种task_ struct内容分类 组织进程查看进程通过系统调用获取进程标示符通过系统调用创建进程——fork初识 作者&#xff…

Android 中 app freezer 原理详解(二):S 版本

基于版本&#xff1a;Android S 0. 前言 在之前的两篇博文《Android 中app内存回收优化(一)》和 《Android 中app内存回收优化(二)》中详细剖析了 Android 中 app 内存优化的流程。这个机制的管理通过 CachedAppOptimizer 类管理&#xff0c;为什么叫这个名字&#xff0c;而不…

青大数据结构【2016】

一、单选 二、简答 3.简述遍历二叉树的含义及常见的方法。

大数据面试题:HBase的RegionServer宕机以后怎么恢复的?

面试题来源&#xff1a; 《大数据面试题 V4.0》 大数据面试题V3.0&#xff0c;523道题&#xff0c;679页&#xff0c;46w字 可回答&#xff1a;1&#xff09;HBase一个节点宕机了怎么办&#xff1b;2&#xff09;HBase故障恢复 参考答案&#xff1a; 1、HBase常见故障 导…

【构造】CF1758 C

Problem - 1758C - Codeforces 题意&#xff1a; 思路&#xff1a; 思路&#xff1a; #include <bits/stdc.h>#define int long longusing namespace std;const int mxn2e510; const int mxe2e510;int N,x; int ans[mxn];void solve(){cin>>N>>x;if(N%x!0)…

使用MyBatis(2)

目录 一、定义接口、实体类、创建XML文件实现接口&#xff09; 二、MyBatis的增删改查 &#x1f345;1、MyBatis传递参数查询 &#x1f388;写法一 &#x1f388;写法二 &#x1f388;两种方式的区别 &#x1f345;2、删除操作 &#x1f345;3、根据id修改用户名 &#x…

机器学习-Basic Concept

机器学习(Basic Concept) videopptblog Where does the error come from? 在前面我们讨论误差的时候&#xff0c;我们提到了Average Error On Testing Data是最重要的 A more complex model does not lead to better performance on test data Bias And Variance Bias(偏差) …

反转链表(JS)

反转链表 题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1]示例 3&…

三数之和——力扣15

文章目录 题目描述法一 双指针排序 题目描述 法一 双指针排序 class Solution{ public:vector<vector<int>> threeSum(vector<int>& nums){int nnums.size();vector<vector<int>> ans;sort(nums.begin(), nums.end());for(int first0;first&…

死锁产生的原因及解决方案

死锁 1. 死锁的成因2. 解决方案 1. 死锁的成因 互斥条件: 一个资源每次只能被一个进程使用。请求与保持条件&#xff1a;一个进程因请求资源而阻塞时&#xff0c;对已获得的资源保持不放。不可剥夺条件:进程已获得的资源&#xff0c;在末使用完之前&#xff0c;不能强行剥夺。…