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;
        }
    
  • 相关阅读:
    三大主流负载均衡软件对比(LVS+Nginx+HAproxy)
    nginx 提示the "ssl" directive is deprecated, use the "listen ... ssl" directive instead
    centos安装nginx并配置SSL证书
    hadoop创建目录文件失败
    The server time zone value 'EDT' is unrecognized or represents more than one time zone.
    脚本启动SpringBoot(jar)
    centos做免密登录
    数据库远程连接配置
    Bash 快捷键
    TCP三次握手四次断开
  • 原文地址:https://www.cnblogs.com/ruonan1997/p/15234513.html
Copyright © 2011-2022 走看看