单调栈-找到左边/右边第一个比自己小/大的元素

1. 问题描述:

已知一个int类型的整型数组,在nums数组中找到左边或者右边第一个(下一个)比自己小或者大的元素。

2. 思路分析:

这是经典的单调栈的题目,我们可以在遍历nums数组元素的时候维护一个单调栈,主要分为以下几种情况:

  • 左边第一个比自己小的元素
  • 左边第一个比自己大的元素
  • 右边第一个比自己小的元素
  • 右边第一个比自己大的元素

分析题目的条件可知我们可以根据找的是左边还是右边来确定nums数组的遍历顺序,如果是左边那么我们可以从逆序遍历nums数组(这样在弹出栈顶元素的时候可以依次更新右边元素对应的值),如果是右边那么从下标为0正序遍历nums数组,根据比自己小还是比自己大确定循环中比较的条件,并且在弹出栈顶元素的时候更新答案,表示栈中存储的元素对应的答案都是需要被更新的,也即栈中所有元素遇到的当前元素是第一个满足条件的元素。

3. 代码如下:

找到左边第一个比自己小的元素:

from typing import List
import random


class Solution:
    def monoStack(self, nums: List[int]):
        n = len(nums)
        res = [-1] * n
        stack = list()
        for i in range(n - 1, -1, -1):
            # 因为找到的是左边第一个比自己小的所以当栈顶元素大于了当前元素的时候说明需要弹出元素
            while stack and nums[stack[-1]] > nums[i]:
                # 这里可以根据题目的需求更新下标或者具体的值
                res[stack[-1]] = nums[i]
                stack.pop()
            # 存储的是元素的下标这样可以通过下标获得对应的元素值
            stack.append(i)
        return res


if __name__ == '__main__':
    nums = list()
    n = 10
    # 生成10个随机数
    for i in range(n):
        nums.append(random.randint(1, n))
    print(nums)
    print(Solution().monoStack(nums))

acwing中找到左边第一个比自己小的元素网址

from typing import List


class Solution:
    def monoStack(self, nums: List[int]):
        n = len(nums)
        res = [-1] * n
        stack = list()
        for i in range(n - 1, -1, -1):
            while stack and nums[stack[-1]] > nums[i]:
                res[stack[-1]] = nums[i]
                stack.pop()
            stack.append(i)
        return res


if __name__ == '__main__':
    n = int(input())
    nums = list(map(int, input().split()))
    nums = Solution().monoStack(nums)
    for x in nums:
        print(x, end=" ")

找到左边第一个比自己大的元素:

from typing import List
import random


class Solution:
    def monoStack(self, nums: List[int]):
        n = len(nums)
        res = [-1] * n
        stack = list()
        for i in range(n - 1, -1, -1):
            while stack and nums[stack[-1]] < nums[i]:
                res[stack[-1]] = nums[i]
                stack.pop()
            stack.append(i)
        return res


if __name__ == '__main__':
    nums = list()
    n = 10
    for i in range(n):
        nums.append(random.randint(1, n))
    print(nums)
    print(Solution().monoStack(nums))

找到右边第一个比自己小的元素:

from typing import List
import random


class Solution:
    def monoStack(self, nums: List[int]):
        n = len(nums)
        res = [-1] * n
        stack = list()
        for i in range(n):
            while stack and nums[stack[-1]] > nums[i]:
                res[stack[-1]] = nums[i]
                stack.pop()
            stack.append(i)
        return res


if __name__ == '__main__':
    nums = list()
    n = 10
    for i in range(n):
        nums.append(random.randint(1, n))
    print(nums)
    print(Solution().monoStack(nums))

找到右边第一个比自己大的元素:

from typing import List
import random


class Solution:
    def monoStack(self, nums: List[int]):
        n = len(nums)
        res = [-1] * n
        stack = list()
        for i in range(n):
            while stack and nums[stack[-1]] < nums[i]:
                res[stack[-1]] = nums[i]
                stack.pop()
            stack.append(i)
        return res


if __name__ == '__main__':
    nums = list()
    n = 10
    for i in range(n):
        nums.append(random.randint(1, n))
    print(nums)
    print(Solution().monoStack(nums))
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值