算法从入门到放弃——第五期 单调栈

本文解析了如何使用单调栈算法解决LeetCode中的经典问题,通过实例演示如何找出循环数组中每个元素的下一个更大元素。理解栈的操作和何时入栈、出栈,有助于提升算法理解。

单吊顾名思义,就是听牌之后胡一张的打法。。。。拿错课本了不好意思

大部分的算法题你做不出来的原因,都是你没找到合适的方法,更简单的说就是你没见过更合适的方法,更关乎知识的广度,比如今天所说的单调栈

大部分算法只要你脑袋里面能流畅的想象出整个过程,写出代码debug一下,基本就能AC,单调栈的代码很简单,但是却不是那么好复现过程。

leetcode里面最典型的题就是利用单调栈解找下一个最大的问题,理解单调栈有点像你最开始理解dp数组一样,你得明白它含义是什么,搞清楚什么含义,会更快,上题目:

给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

示例 1:

输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数; 
第二个 1 的下一个最大的数需要循环搜索,结果也是 2

给大家用所谓单调栈还原一下整个过程,不过我们换个数组

输入nums[] = [1,1,0,2,1,4]

结果res[] = [-1...]因为找不到就是-1,初始化-1不用额外去填写

单调栈中存储的内容就是还没有找到下一个比自己大的元素的下标将要入栈的是下一次要找比自己大元素的下标

操作上遍历数组开始即可,栈中为空,正常入栈

(1)栈:【】,index = 0,栈为空,正常入栈 ,此时  栈:【0】

(2)栈:【0】,index = 1,栈不为空,1是上一个没有找到比自己大的元素的下标,比较nums[0]和nums[1(index)],此时index=0元素还是没有找到比自己大的元素,不出栈,index=1元素入栈

此时 栈:【0,1】

(3)栈:【0,1】index = 2,1是上一个没有找到比自己大的元素的下标,比较nums[1]和nums[2],此时index=1元素还是没有找到比自己大的元素,不出栈,index=2元素入栈

(4)栈:【0,1,2】index = 3,2是上一个没有找到比自己大的元素的下标,比较nums[2]和nums[3],此时index=2元素找到比自己大的元素,那么index = 2 必须出栈,res[2(栈顶元素下标)] = nums[3(index)],此时 栈:【0,1】,由于nums[3]>nums[2]有可能也大于nums[1],那么继续比较栈顶元素nums[1]和当前元素nums[3(index)],由于nums[3]>nums[1],那么1也要出栈,并且res[1]=nums[3],同理,栈中0元素也出栈,栈为空。至此,之前所有元素均找到比自己大的元素。

还没结束,此时index = 3是下次要找比自己大元素的下标,所以3入栈,此时 栈【3】

循环。。。。

上面(1,2)步,是nums[i]=nums[j]的情况,(2,3)步,是nums[i]>nums[j]的情况,(3,4)步时nums[i]<nums[j]的情况,验证了一下可行性

总体一句话:

栈中的元素是:已经遍历了,但是还没找到比自己大元素的下标

将要入栈的是:要比较的目标下标,也是还没找到比自己大元素的下标,是下一次比较的起点,无论如何必须入栈

相信你复制下面代码debug一下过程,会有更深刻的印象:

代码:

    public static int[] nextGreaterElements(int[] nums) {
        int length = nums.length;
        int[] res = new int[length];
        Arrays.fill(res,-1);
        Stack<Integer> stack = new Stack<>();
        for(int i =0;i<length*2;i++){
            int index = i%length;
            while (!stack.isEmpty()&&nums[stack.peek()]<nums[index]){
                res[stack.pop()] = nums[index];
            }
            stack.push(index);
        }
        return res;
    }

时间复杂度n,是不是有了方法就很简单的一道中等题?

当然,找下一个比自己大元素还有经典的双指针法,不过时间复杂度n2,以上

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值