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

分析网站网站海外独立站

分析网站网站,海外独立站,动态网站开发多少钱,东莞网站建设纸品包装单调栈一文深度解析 一、单调栈基础概念1.1 定义与核心特性1.2 与普通栈的区别1.3 核心操作模板 二、单调栈核心原理2.1 单调性维护机制2.2 典型应用场景 三、经典案例解析下一个更大元素问题描述思路分析代码实现复杂度分析 接雨水问题问题描述思路分析代码实现复杂度分析 柱状…

单调栈一文深度解析

    • 一、单调栈基础概念
      • 1.1 定义与核心特性
      • 1.2 与普通栈的区别
      • 1.3 核心操作模板
    • 二、单调栈核心原理
      • 2.1 单调性维护机制
      • 2.2 典型应用场景
    • 三、经典案例解析
      • 下一个更大元素
        • 问题描述
        • 思路分析
        • 代码实现
        • 复杂度分析
      • 接雨水问题
        • 问题描述
        • 思路分析
        • 代码实现
        • 复杂度分析
      • 柱状图最大面积
        • 问题描述
        • 思路分析
        • 代码实现
        • 复杂度分析
    • 四、单调栈解题模板
      • 4.1 通用解题步骤
      • 4.2 常见问题映射表
    • 五、进阶技巧与优化
      • 5.1 双向单调栈
      • 5.2 单调栈与动态规划结合
      • 5.3 注意事项

单调栈是一种专门处理元素间序关系的高效数据结构,它通过维护栈内元素的单调性,能够在线性时间内解决诸如下一个更大/小元素系列经典问题。本文我将从单调栈的核心原理出发,结合经典案例,解析并总结其解题模板及优化技巧,帮你掌握这一高效解题工具。

一、单调栈基础概念

1.1 定义与核心特性

单调栈是指栈内元素(从栈底到栈顶)保持单调递增或单调递减的栈结构。根据单调性不同,分为:

  • 单调递增栈:栈内元素始终满足 stack[i] <= stack[i+1]
  • 单调递减栈:栈内元素始终满足 stack[i] >= stack[i+1]

其核心特性是:当新元素入栈时,通过弹出栈顶不满足单调性的元素,确保栈内元素始终保持单调。这种特性使得单调栈能够高效处理「元素与周边元素的序关系」问题。
单调递增栈

1.2 与普通栈的区别

特性普通栈单调栈
元素顺序无约束严格单调
主要操作push/pop维护单调性
典型场景表达式求值序关系问题
时间复杂度不定均摊O(n)

1.3 核心操作模板

// 单调递增栈模板
Stack<Integer> stack = new Stack<>();
for (int num : nums) {while (!stack.isEmpty() && stack.peek() >= num) { // 破坏递增性时弹出int poped = stack.pop();// 处理弹出元素}stack.push(num); // 新元素入栈,确保栈递增
}// 单调递减栈模板
Stack<Integer> stack = new Stack<>();
for (int num : nums) {while (!stack.isEmpty() && stack.peek() <= num) { // 破坏递减性时弹出int poped = stack.pop();// 处理弹出元素}stack.push(num); // 新元素入栈,确保栈递减
}

二、单调栈核心原理

2.1 单调性维护机制

  • 入栈规则:新元素入栈前,弹出所有破坏单调性的栈顶元素
  • 元素处理:弹出元素时,当前新元素即为其「下一个更大/更小元素」
  • 均摊复杂度:每个元素最多入栈/出栈一次,总时间复杂度O(n)
    单调递减栈维护

2.2 典型应用场景

  1. 下一个更大元素:数组中每个元素右侧第一个比它大的元素
  2. 接雨水问题:计算柱状图能接的雨水总量
  3. 柱状图最大面积:求解直方图中的最大矩形面积
  4. 每日温度:计算每天需要等待多久才会升温
  5. 股票买卖问题:寻找最佳买卖时机的变种问题

三、经典案例解析

下一个更大元素

问题描述

给定数组nums,返回一个新数组,其中每个元素是原数组对应位置元素的下一个更大元素(右侧第一个比它大的元素,不存在则为-1)。

思路分析
  • 使用单调递增栈,栈中保存尚未找到下一个更大元素的元素下标
  • 遍历数组时,新元素与栈顶元素比较:
    • 若新元素更大:栈顶元素的下一个更大元素即为当前元素,弹出并记录
    • 否则:新元素下标入栈
代码实现
public int[] nextGreaterElement(int[] nums) {int[] res = new int[nums.length];Stack<Integer> stack = new Stack<>(); // 存储下标,栈中元素对应的值单调递增for (int i = nums.length - 1; i >= 0; i--) {while (!stack.isEmpty() && nums[stack.peek()] <= nums[i]) {stack.pop(); // 弹出不满足递增的元素}res[i] = stack.isEmpty() ? -1 : nums[stack.peek()];stack.push(i);}return res;
}
复杂度分析
  • 时间复杂度:O(n),每个元素入栈出栈各一次
  • 空间复杂度:O(n),栈空间最多存储n个元素

接雨水问题

问题描述

给定n个非负整数表示柱状图的高度,计算下雨后能接多少雨水。

思路分析
  • 单调栈解法:维护单调递减栈,栈中存储柱子下标
  • 当新柱子高度 >= 栈顶柱子高度时,弹出栈顶,计算中间凹槽的接水量
  • 接水量由左右边界的较小值减去中间柱子高度决定
代码实现
public int trap(int[] height) {int res = 0;Stack<Integer> stack = new Stack<>(); // 存储下标,栈中高度单调递减for (int i = 0; i < height.length; i++) {while (!stack.isEmpty() && height[i] >= height[stack.peek()]) {int mid = stack.pop();if (stack.isEmpty()) break; // 没有左边界,无法形成凹槽int left = stack.peek();int width = i - left - 1;int h = Math.min(height[left], height[i]) - height[mid];res += width * h;}stack.push(i);}return res;
}
复杂度分析
  • 时间复杂度:O(n),每个元素入栈出栈各一次
  • 空间复杂度:O(n),栈空间最多存储n个元素

柱状图最大面积

问题描述

给定直方图的高度数组,求其中最大矩形面积。

思路分析
  • 单调递增栈:栈中存储下标,对应高度单调递增
  • 每个元素出栈时,视为矩形的高,宽度由左右边界决定:
    • 左边界:栈顶元素(弹出后的新栈顶)
    • 右边界:当前元素下标
    • 宽度 = 右边界 - 左边界 - 1
代码实现
public int largestRectangleArea(int[] heights) {int res = 0;Stack<Integer> stack = new Stack<>(); // 存储下标,栈中高度单调递增int[] newHeights = Arrays.copyOf(heights, heights.length + 2); // 首尾加0,避免边界处理for (int i = 0; i < newHeights.length; i++) {while (!stack.isEmpty() && newHeights[i] < newHeights[stack.peek()]) {int h = newHeights[stack.pop()];int w = i - stack.peek() - 1;res = Math.max(res, h * w);}stack.push(i);}return res;
}
复杂度分析
  • 时间复杂度:O(n),每个元素入栈出栈各一次
  • 空间复杂度:O(n),栈空间及辅助数组

四、单调栈解题模板

4.1 通用解题步骤

  1. 确定单调性:根据问题确定使用递增栈还是递减栈(找更大元素用递增栈,找更小元素用递减栈)
  2. 定义栈存储内容:通常存储元素下标(便于计算距离),而非直接存储元素值
  3. 处理边界条件:通过虚拟边界(如首尾加0)简化边界判断
  4. 元素弹出逻辑:当新元素破坏单调性时,弹出栈顶元素并计算相关结果

4.2 常见问题映射表

问题类型单调性栈存储弹出条件结果计算方式
下一个更大元素递增栈下标新元素 > 栈顶元素新元素为栈顶元素的下一个更大元素
柱状图最大面积递增栈下标新元素 < 栈顶元素栈顶元素为高,左右边界算宽度
接雨水递减栈下标新元素 >= 栈顶元素栈顶元素为中间柱,算凹槽水量
每日温度递增栈下标新元素温度 > 栈顶温度天数为下标差

五、进阶技巧与优化

5.1 双向单调栈

对于需要同时考虑左右边界的问题(如接雨水问题),可分别使用左右单调栈计算每个位置的左右最大高度,再取较小值计算水量。虽然时间复杂度同为O(n),但代码逻辑更清晰:

// 接雨水双向栈解法
public int trap(int[] height) {int n = height.length;int[] leftMax = new int[n];int[] rightMax = new int[n];// 左单调栈(递增)Stack<Integer> leftStack = new Stack<>();for (int i = 0; i < n; i++) {while (!leftStack.isEmpty() && height[leftStack.peek()] <= height[i]) {leftStack.pop();}leftMax[i] = leftStack.isEmpty() ? 0 : height[leftStack.peek()];leftStack.push(i);}// 右单调栈(递增)Stack<Integer> rightStack = new Stack<>();for (int i = n-1; i >= 0; i--) {while (!rightStack.isEmpty() && height[rightStack.peek()] <= height[i]) {rightStack.pop();}rightMax[i] = rightStack.isEmpty() ? 0 : height[rightStack.peek()];rightStack.push(i);}int res = 0;for (int i = 0; i < n; i++) {res += (Math.min(leftMax[i], rightMax[i]) - height[i]);}return res;
}

5.2 单调栈与动态规划结合

在「股票买卖的最佳时机」系列问题中,可结合单调栈优化动态规划的状态转移,将O(n²)的暴力解法优化至O(n),我将在之后的博客中进行讲解,持续关注不错过哦。

5.3 注意事项

  • 下标与值的区分:栈中存储下标而非值,便于计算元素间的距离(如宽度、天数差)
  • 虚拟元素处理:通过在数组首尾添加虚拟元素(如0),避免单独处理边界条件
  • 单调性方向判断:明确问题需要「更大」还是「更小」元素,选择对应的单调栈类型

单调栈通过维护元素的单调性,将原本需要双重循环的序关系问题优化至线性时间,是解决「下一个更大/更小元素」类问题的核心工具。其核心思想是:用栈结构缓存尚未处理的元素,通过单调性约束快速确定元素间的序关系

That’s all, thanks for reading!
觉得有用就点个赞、收进收藏夹吧!关注我,获取更多干货~

http://www.dtcms.com/wzjs/474513.html

相关文章:

  • 做网站的目的怎么开通百度推广账号
  • 推广型网站建设地址武汉搜索推广
  • WordPress星光主题上海seo优化
  • linux服务器做网站聊城网站推广公司
  • 南宁网站制作公竞价排名营销
  • 厦门seo排名收费如何点击优化神马关键词排名
  • 用什么程序做资讯类网站常见的网络营销策略都有哪些
  • 做棋牌网站一般多少钱百度官方app免费下载
  • 有人做家具网站中介吗排名优化
  • python培训视频合作seo公司
  • 网站架设标准广州网站优化方案
  • 网站建设及维护成本杭州seo网站优化公司
  • 南阳做个网站多少钱百度框架户一级代理商
  • 在线网站建设诚信经营网络营销考试答案
  • 镇江网站建设远航科技北京优化推广公司
  • 深圳网站建设选哪家建站seo推广
  • 网站备案名 企业名软文写作方法
  • web前端毕业论文题目seo关键词排名优化销售
  • 网站关键词分布情况网络销售怎么做才能做好
  • 怎么登陆wordpress后台seo外链增加
  • 衡阳网站排名优化公司百度竞价排名商业模式
  • 建材企业网站营销怎么做网络营销网络推广
  • 网站建设公司山西windows7优化大师下载
  • 大连网站建设哪个好三叶草gw9356
  • 深圳哪家网站建设服务好软文写作范文500字
  • 无锡网站建设外包优势互联网营销培训课程
  • 四川微信网站建设seo网站查询
  • 类似稿定设计的软件有哪些网站优化及推广
  • 织梦企业网站管理系统2020国内搜索引擎排行榜
  • 湖南网站建设公司排行榜微信推广怎么做