当前位置: 首页 > news >正文

每日算法刷题Day58:8.7:leetcode 单调栈5道题,用时2h

二.进阶

1.套路
2.题目描述
3.学习经验
1. 1019.链表中的下一个更大节点(中等)

1019. 链表中的下一个更大节点 - 力扣(LeetCode)

思想

1.给定一个长度为 n 的链表 head
对于列表中的每个节点,查找下一个 更大节点 的值。也就是说,对于每个节点,找到它旁边的第一个节点的值,这个节点的值 严格大于 它的值。
返回一个整数数组 answer ,其中 answer[i] 是第 i 个节点( 从1开始 )的下一个更大的节点的值。如果第 i 个节点没有下一个更大的节点,设置 answer[i] = 0 。
2.查找下一个更大节点的值就想到单调栈

代码
/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:typedef pair<int, int> PII; // 下标-值vector<int> nextLargerNodes(ListNode* head) {int n = 0;ListNode* tmp = head;while (tmp) {++n;tmp = tmp->next;}vector<int> res(n, 0);vector<PII> stk;int id = 0;tmp = head;while (tmp) {while (!stk.empty() && tmp->val > stk.back().second) {res[stk.back().first] = tmp->val;stk.pop_back();}stk.push_back({id, tmp->val});++id;tmp = tmp->next;}return res;}
};

二.矩形

1.套路

1.可以枚举矩形的高,找左边和右边第一个比它小的下标leftright,用单调栈

2. 题目描述
3. 学习经验
1. 84. 柱状图中最大的矩形(困难,学习)

84. 柱状图中最大的矩形 - 力扣(LeetCode)

思想

1.给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
2.可以得出最大矩形的高肯定是数组里面的高,反证法证明即可。
这一点确定了,就可以枚举矩形的高,然后符合条件的矩形要求左右高度都大于等于它,那么就要找左边第一个比它小的下标left.和右边第一个比它小的下标right,那么宽度范围就是(left,right),宽度为right=left-1,而找第一个比它小的下标就是单调栈,找两次即可。
因为左右是开区间,所以left初值为-1,right初值为n

代码
class Solution {
public:int largestRectangleArea(vector<int>& heights) {int n = heights.size();int res = 0;vector<int> left(n, -1);vector<int> right(n, n);vector<int> stk;for (int i = n - 1; i >= 0; --i) {while (!stk.empty() && heights[i] < heights[stk.back()]) {left[stk.back()] = i;stk.pop_back();}stk.push_back(i);}stk.clear();for (int i = 0; i < n; ++i) {while (!stk.empty() && heights[i] < heights[stk.back()]) {right[stk.back()] = i;stk.pop_back();}stk.push_back(i);}for (int i = 0; i < n; ++i) {// 宽为(left[i],right[i])res = max(res, heights[i] * (right[i] - left[i] - 1));}return res;}
};

三.贡献法

1.套路
2. 题目描述
3. 学习经验
1. 907. 子数组的最小值之和(中等,学习)

907. 子数组的最小值之和 - 力扣(LeetCode)

思想

1.给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。
由于答案可能很大,因此 返回答案模 10^9 + 7 。
2,此题和[[七.单调栈#1. 84. 柱状图中最大的矩形(困难,学习)]]一样,以枚举arr[i]为视角,找它是最小值的范围,即左边第一个比它小的下标left,和右边比它小的下标right,然后求子数组,左边元素可以选(left,i].右边元素可以选[i,right),再按照乘法原理(i-left)*(right-i)得到arr[i]作为最小元素的子数组数量。
但是上面只能算无重复元素的,对于包含重复元素的,如下面例子:
arr=[1,2,4,2,3,1],若按上述算法,两个2的边界都是(0,5),会重复算,可以把一个边界变成第一个大于等于它的下标,以右边界为例,第一个2的边界是(0,3),第2个2的边界是(0,5),所以右边的重复元素把左边的重复元素的右边界给截断了,不会出现重复算

代码

四.最小字典序

1.套路

1.删除序列某些元素,保证序列相对顺序不变,使得剩下序列字典序最小。
即遇到后面元素,根据条件判断删除前面元素,用栈实现。
但是前提条件是未达到删除数量,所以要提前知道删除数量。
同时遍历完可能未删完,还要遍历删除数量再删除序列后面元素,保证删够数量。

class Solution {
public:vector<int> mostCompetitive(vector<int>& nums, int k) {int n = nums.size();// 删除数量int shan = n - k;vector<int> stk;for (int i = 0; i < n; ++i) {// 未删完且要删while (!stk.empty() && shan > 0 && stk.back() > nums[i]) {stk.pop_back();--shan;}stk.push_back(nums[i]);}// 未删完while (shan) {stk.pop_back();--shan;}return stk;}
};
2. 题目描述
3. 学习经验
1. 402. 移除K位数字(中等,学习)

402. 移掉 K 位数字 - 力扣(LeetCode)

思想

1.给你一个以字符串表示的非负整数 num 和一个整数 k ,移除这个数中的 k 位数字,使得剩下的数字最小。请你以字符串形式返回这个最小的数字。
2.这题首先利用贪心思想,若还可以移除元素,且遍历到的数字比前一个数字小,则可以把前一个数字出栈,则先进后出,利用栈实现,则上述逻辑可以保证在一段区间内单调递增。但是会有以下问题:

  • 未删除k个元素,则还要再遍历k,将栈中末尾元素弹出
  • 若当前栈前面是前导0,则把栈中元素转移到答案中,要先保证没有前导0
  • 答案为空串,对应数字为0
代码
class Solution {
public:string removeKdigits(string num, int k) {int n = num.size();vector<char> stk;int len = n - k;for (int i = 0; i < n; ++i) {while (!stk.empty() && num[i] < stk.back() && k > 0) {stk.pop_back();--k;}stk.push_back(num[i]);}for (; k > 0; --k)stk.pop_back();bool isLeadingZero = true;string res = "";for (auto& c : stk) {if (isLeadingZero && c == '0')continue;isLeadingZero = false;res += c;}return res == "" ? "0" : res;}
};
2. 1673. 找出最具竞争力的子序列(中等)

1673. 找出最具竞争力的子序列 - 力扣(LeetCode)

思想

1.给你一个整数数组 nums 和一个正整数 k ,返回长度为 k 且最具 竞争力 的 nums 子序列。
数组的子序列是从数组中删除一些元素(可能不删除元素)得到的序列。
在子序列 a 和子序列 b 第一个不相同的位置上,如果 a 中的数字小于 b 中对应的数字,那么我们称子序列 a 比子序列 b(相同长度下)更具 竞争力 。 例如,[1,3,4] 比 [1,3,5] 更具竞争力,在第一个不相同的位置,也就是最后一个位置上, 4 小于 5 。
2.依旧是判断当前遍历元素小于前一元素时,删去前一元素,用栈实现。但删的前提是没达到删除上限,这题得先算一下删除数量。
依旧遍历完可能没删完,再遍历删除数量保证删完。

代码
class Solution {
public:vector<int> mostCompetitive(vector<int>& nums, int k) {int n = nums.size();int shan = n - k;vector<int> stk;for (int i = 0; i < n; ++i) {while (!stk.empty() && shan > 0 && stk.back() > nums[i]) {stk.pop_back();--shan;}stk.push_back(nums[i]);}while (shan) {stk.pop_back();--shan;}return stk;}
};
http://www.dtcms.com/a/320410.html

相关文章:

  • 零基础-动手学深度学习-9.3. 深度循环神经网络
  • Langchain入门:对话式RAG
  • Tool Learning的基本概念及应用
  • 数据结构——栈、队列
  • python题目练习 无重叠区间
  • Linux学习-数据结构(二叉树)
  • 嵌入式开发学习———Linux环境下IO进程线程学习(六)
  • 了解大型语言模型:力量与潜力
  • SpringBoot学习日记 Day5:解锁企业级开发核心技能
  • PCIe Base Specification解析(九)
  • 多线程的使用
  • 2025 最新 ECharts 下载、安装与配置教程
  • Linux 中断系统全览解析:从硬件到软件的全路线理解
  • Oracle 19C In-Memory 列存储技术测试
  • Qwen系列模型
  • [链表]两两交换链表中的节点
  • 【感知机】感知机(perceptron)学习算法的对偶形式
  • aurora rx没有ready信号
  • 哈希表——指针数组与单向链表的结合
  • linux顽固进程查看并清理
  • Java包装类详解与应用指南
  • SupChains技术团队:需求预测中减少使用分层次预测(五)
  • 目标检测数据集 - 眼睛瞳孔检测数据集下载「包含COCO、YOLO两种格式」
  • 菜鸟笔记007 [...c(e), ...d(i)]数组的新用法
  • (数据结构)顺序表实现-增删查改
  • java中override和overload的区别
  • 敏捷总结-上
  • 如果获取Docker镜像
  • Flink与Kafka核心源码详解-目录
  • 中国北极圈战略部署