zoukankan      html  css  js  c++  java
  • 单调栈系列

    单调栈系列

    单调栈实际上就是栈,只是利用了一些巧妙的逻辑,使得每次新元素入栈后,栈内的元素都保持有序(单调递增或单调递减)。

    题目列表

    1、496 Next Great Element

    2、739 Daily Temperature

    3、503 Next Greater Element II

    496 Next Great Element

    题目描述

    这道题如果暴力解法的话很容易想到,直接遍历该数字后面的数,然后返回值即可。时间复杂度O(n1);

    可以换一个方式思考,这里我们先上代码,方便解释;

     public int[] nextGreaterElement(int[] nums1, int[] nums2) {
            Map<Integer,Integer> map =new HashMap<>();
            int n2 =nums2.length;
            Stack<Integer> s = new Stack<Integer>();
            for (int i = n2-1; i >= 0; i--) {
                while(!s.isEmpty() && s.peek()<=nums2[i]){
                    s.pop();
                }
                map.put(nums2[i],s.isEmpty()? -1: s.peek());
                s.add(nums2[i]);
            }
            int n1 = nums1.length;
            int[] ans =new int[n1];
            for (int i = 0; i < n1; i++) {
                ans[i] = map.get(nums1[i]);
            }
            return ans;
        }
    

    我们先求出nums2中每个数的next great element,然后存HashMap中,再遍历nums1在HashMap找到所求结果。

    关键在于nums2中如何求得每一个数的next great element呢?

    这里我们先创建栈,然后在栈中排出比当前nums2[i]小的值,如果栈S不为空,得到的s.peek()就是nums2[i]的next great element了。最后我们将nums2[i]添加进栈,就完成了单调栈的整个过程。

    注意点:我们需要从后面向前遍历,这样我们才能够得到next great element,如果是从前向后遍历的话,得到就是 previous great number了。(想一想是不是这个道理)

    虽然是for循环嵌套while,但是这个算法的时间复杂度为O(n);因为每个元素进栈一次,并且最多也只会被pop一次,所以时间复杂度为O(n)。

    739 Daily Temperature

    题目描述

    这道题求的是隔了几天才会有更高的温度,我们只需要将元素的下标进栈即可。

    public int[] dailyTemperatures(int[] temperatures) {
          int n = temperatures.length;
            int[] ans = new int[n];
            Stack<Integer> s = new Stack<>();
            for (int i = n - 1; i >= 0; i--) {
                while (!s.isEmpty() && temperatures[s.peek()] <= temperatures[i]) {
                s.pop();
                }
                ans[i] = s.isEmpty()? 0:s.peek()-i;
                s.add(i);
            }
            return ans;
        }
    

    503 Next Greater Element II

    注意到这里数组变成了环形数组,解决这一类问题的套路就是将数组的长度翻倍;

    实际操作中也并不需要翻倍数组,而是将下标翻倍即可

    public int[] nextGreaterElements(int[] nums) {
            int n = nums.length;
            int n2 = 2*n;
            int[] ans = new int[n];
            Stack<Integer> s = new Stack<Integer>();
            for (int i = n2-1; i >= 0; i--) {
                while(!s.isEmpty() && s.peek()<=nums[i%n]){
                    s.pop();
                }
                if(i<=n-1){
                    ans[i] = s.isEmpty()? -1:s.peek();
                }
                s.add(nums[i%n]);
            }
            return ans;
        }
    
  • 相关阅读:
    html添加遮罩层
    html绝对定位如何居中
    springboot上传文件到本地服务器
    遍历一个文件目录,把所有的子目录都列出来
    Java判断cookie中是否有某个具体的cookie
    Redis 如何打开rdb 文件
    crontab -e 如何保存退出
    linux服务器设备上没有空间
    IDEA的SonarLint插件报错Unable to create symbol table for
    使用Rome读取RSS报错,org.xml.sax.SAXParseException: 前言中不允许有内容。
  • 原文地址:https://www.cnblogs.com/ruonan1997/p/15234513.html
Copyright © 2011-2022 走看看