算法_单调栈

单调栈

1、应用场景

一般都是在一个数组中,一个数a,找到a左(右)边第一个大(小)于a的数 这类问题我们可以用暴力循环来做,直接从a开始循环,然后从左或者从右指定的元素即可。但是时间复杂度比较高,使用栈来优化。

2、例题

AcWing830.单调栈

此题就是单调栈的经典应用,找出数组中每一个元素的左边第一个比他小的数

暴力做法

暴力做法就是双重循环,第一重遍历每个元素array[i],第二重循环从元素的左边第一个位置开始遍历,一直往前找,直到找到一个小于array[i]的数返回,找不到输出-1

跟暴力做法基本一致的还可以使用一个栈,每遍历一个元素,就将它左边的元素从右往左全部入栈,然后一一的找小于目标元素的 单调栈优化的就是这种做法,我们可以发现,当存在下面的关系时,则寻找y后面的元素的左边第一个最小值时,array[x]永远不会作为它的结果,所以我们就可以维护一个单调栈,是里面的元素永远是单调递增(减)的,这样每次遍历元素时,就不需要将其左边的元素全部入栈,而直接从栈中找答案即可。

x < y
array[x] > array[y]

单调栈示例

举例 :3 4 2 7 5

找出这个数组中每一个元素的左边第一个比他小的数。我们模拟一下过程

我们创建一个栈 
------------------------------------------------------------------------------
3入栈
入栈时栈为空,说明3的左边没有比它小的数,然后将3入栈
此时栈中 3      
------------------------------------------------------------------------------ 
4入栈
此时栈顶元素为34小,所以4的结果就是3 然后将4入栈
 此时栈中  
 		  4 
          3    
------------------------------------------------------------------------------
2入栈
    2比栈顶元素4小,说明2后面的数的答案就不可能是4了,将4出栈
    然后栈顶时3 也比2小,同理也出栈 此时栈空,说明左边没有比2小的数
    最后将2入栈
    此时栈中   2
------------------------------------------------------------------------------
7入栈   
    7比栈顶元素2大,2就是7的答案,然后将7入栈    
    此时栈中
           7
           2
------------------------------------------------------------------------------
5入栈
    5比栈顶元素7小,将7出栈,然后与2比较 大于2,那么2就是5的答案
	最后将5入栈 
    此时栈中 
    		 5 
             2

经过上面的解释我们可以发现,栈中的元素从上到下一直都是单调递减的,我们也不需要每次都将某一元素左边的元素全部入栈然后找答案,只需要维护一个单调栈然后直接去栈中找答案即可。核心就是靠上面的性质

代码

扫描二维码关注公众号,回复: 13358452 查看本文章
import java.util.Scanner;
import java.util.Stack;

public class Main{
    
    

    public static void main(String[] args){
    
    
        Stack<Integer> stack = new Stack();
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        for(int i = 0; i < n;i++){
    
    
               int x = cin.nextInt();
                //当栈不为空且x比栈顶元素大时栈顶元素出栈
                while(!stack.isEmpty() && stack.peek() >= x ) stack.pop();
                //栈为空时说明此元素前面没有比其小的数
                if(stack.isEmpty())System.out.print(-1 + " ");
                //不为空则此时的栈顶元素就是答案
                else System.out.print(stack.peek()+" ");
            	//最后必须将此元素入栈
                stack.push(x);            
        }
    }
}

3、应用

力扣496.下一个更大元素 ——>题解

力扣503.下一个更大元素II——>双指针+单调栈题解

力扣739.每日温度——>此题栈中存的是索引 题解

猜你喜欢

转载自blog.csdn.net/qq_46312987/article/details/119840833