【数据结构与算法】单调栈

本文介绍了如何利用单调栈解决与单调性相关的数组问题,包括不含重复值和含重复值的数组中寻找特定值的问题,以及求最大子矩阵的大小。通过暴力解法和单调栈解法的对比,阐述了单调栈在优化时间复杂度方面的优势。
摘要由CSDN通过智能技术生成

参考《程序员面试指南:IT名企算法于数据结构题目最优解(第2版)》

单调栈

单调栈是一种从栈顶到栈底单调递增单调递减的栈。
它常用于解决离某位置最近的最大或者最小值这种问题。

不含重复值的数组

问题描述

给定一个不含重复值的数组arr,找到每一个i位置左边和右边离i位置最近且值比arr[i]小的位置。返回所有位置相应的信息,不存在则为-1

示例:
输入:arr = [3, 4, 1, 5, 6, 2, 7]
输出:[(-1, 2), (0, 2), (-1, -1), (2, 5), (3, 5), (2, -1), (5, -1)]

暴力解法

时间复杂度为 O ( N 2 ) \mathcal{O}(N^2) O(N2),每个位置分别向左和向右遍历即可。

单调栈解法

时间复杂度为 O ( N ) \mathcal{O}(N) O(N)
大致思路是维护一个单调栈stack和结果数组res,因为是找最小值,所以为从栈顶到栈底单调递减的栈,栈中保存的是arr中的位置。

  • 如果当前遍历到的值比栈顶元素对应arr中的值大,那么直接入栈;
  • 若比栈顶元素对应arr中的值小,那么弹出栈顶元素对应的结果就可确定了,当前遍历的值为其右边最近且比它小的值,新的栈顶元素为其左边最近且比它小的值。
  • 如果arr中元素已经遍历完则判断stack是否为空,若为空,则已经得到最终的结果了,若stack不为空,则需要一次弹出stack的栈顶元素,此时剩下的这些元素不存在位于其右边且比之小的值,所以全部为-1,而只要还有新的栈顶元素即为其左边且比之小的值,如果弹出当前元素后为空,则其res中的值为(-1, -1)
arr = [3, 4, 1, 5, 6, 2, 7]
n = len(arr)
stack, res = [], [None] * n

for i in range(n):
    while stack and arr[i] < arr[stack[-1]]:
        cur = stack.pop()
        left_less = -1 if not stack else stack[-1]
        res[cur] = (left_less, i
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值