当前位置 博文首页 > Explore:单调栈与单调队列算法详解及LeetCode经典题目(Python

    Explore:单调栈与单调队列算法详解及LeetCode经典题目(Python

    作者:[db:作者] 时间:2021-08-14 18:09

    单调栈

    单调栈:栈内的元素按照某种方式排序下单调递增或单调递减,如果新入栈的元素破坏的单调性,就弹出栈内元素,直到满足单调性。

    单调栈分为单调递增栈和单调递减栈:

    • 单调递增栈:栈中数据出栈的序列为单调递减序列;
    • 单调递减栈:栈中数据出栈的序列为单调递增序列。

    维护单调栈

    维护单调递增栈:

    • 遍历数组中每一个元素,执行入栈:每次入栈前先检验栈顶元素和进栈元素的大小。
    • 如果栈空或进栈元素大于栈顶元素则直接入栈;如果进栈元素小于等于栈顶元素,则出栈,直至进栈元素大于栈顶元素。
    for i in range(len(nums)):
    	while stack and nums[i]<=stack.top():
    		stack.pop()
    	stack.push()
    

    维护单调递减栈:

    • 遍历数组中每一个元素,执行入栈:每次入栈前先检验栈顶元素和进栈元素的大小。
    • 如果栈空或进栈元素小于栈顶元素则直接入栈;如果进栈元素大于等于栈顶元素,则出栈,直至进栈元素小于栈顶元素。
    for i in range(len(nums)):
    	while stack and nums[i]>=stack.top():
    		stack.pop()
    	stack.push()
    

    单调栈的作用

    • O ( n ) O(n) O(n)时间复杂度求出某个数的左边或右边第一个比它大或小的元素。

    1. 求第 i i i 个数左边第一个比它小的元素的位置

    • 从左到右遍历元素构造单增栈:一个元素左边第一个比它小的数的位置就是将它插入单增栈时栈顶元素的值,若栈为空,则说明不存在这么一个数。

    举例来说, n u m s = [ 5 , 4 , 3 , 4 , 5 ] nums=[5,4,3,4,5] nums=[5,4,3,4,5],初始时栈空 s t a c k = [ ] stack=[] stack=[]

    • i = 1 i=1 i=1:栈空,左边没有比它小的元素,故 L [ 1 ] = 0 L[1]=0 L[1]=0,同时下标 1 入栈, s t a c k = [ 1 ] stack=[1] stack=[1]
    • i = 2 i=2 i=2:当前元素 4 小于栈顶元素对应的元素 5,故将 1 弹出栈,此时栈空,故 L [ 2 ] = 0 L[2]=0 L[2]=0,然后将元素 4 对应的位置下标 2 入栈, s t a c k = [ 2 ] stack=[2] stack=[2]
    • i = 3 i=3 i=3:当前元素 3 小于栈顶元素对应的元素 4,故将 2 弹出栈,此时栈空,故 L [ 3 ] = 0 L[3]=0 L[3]=0,然后将元素 3 对应的位置下标 3 入栈, s t a c k = [ 3 ] stack=[3] stack=[3]
    • i = 4 i=4 i=4:当前元素 4 大于栈顶元素对应的元素 3,故 L [ 4 ] = s t a c k . t o p ( ) = 3 L[4]=stack.top()=3 L[4]=stack.top()=3,同时将元素 4 对应的下标 4 入栈, s t a c k = [ 3 , 4 ] stack=[3,4] stack=[3,4]
    • i = 5 i=5 i=5:当前元素 5 大于栈顶元素对应的元素 4,故 L [ 5 ] = s t a c k . t o p ( ) = 4 L[5]=stack.top()=4 L[5]=stack.top()=4,同时将元素 5 对应的下标 5 入栈, s t a c k = [ 3 , 4 , 5 ] stack=[3,4,5] stack=[3,4,5]

    2. 求第 i i i 个数左边第一个比它大的元素的位置

    • 从左到右遍历元素构造单减栈:一个元素左边第一个比它大的数的位置就是将它插入单减栈时栈顶元素的值,若栈为空,则说明不存在这么一个数。

    3. 求第 i i i 个数右边第一个比它小的元素的位置

    • 从右到左遍历元素构造单增栈:一个元素右边第一个比它小的数的位置就是将它插入单增栈时栈顶元素的值,若栈为空,则说明不存在这么一个数。
    • 从左到右遍历元素构造单增栈:一个元素右边第一个比它小的数的位置就是将它弹出栈时即将入栈的元素的下标,如果没被弹出栈,说明不存在这么一个数。

    举例来说, n u m s = [ 5 , 4 , 3 , 4 , 5 ] nums=[5,4,3,4,5] nums=[5,4,3,4,5],初始时栈空 s t a c k = [ ] stack=[] stack=[]

    • i = 1 i=1 i=1:栈空,下标1 入栈, s t a c k = [ 1 ] stack=[1] stack=[1]
    • i = 2 i=2 i=