【数据结构系列】单调栈

下一个更大元素I

题目描述

输入一个数组,返回一个等长的数组,对应索引存储着下一个更大的元素,如果没有更大的元素,就存-1;
比如输入一个数组nums = [2,1,2,4,3],算法返回[4,2,4,-1,-1]

解释:第一个2后面比2大的数是4;1后面比1大的数是2;第二个2后面比2大的数是4;4后面没有比4大的数,填-1;3后面没有比3大的数,填-1;

解题思路

单调栈,for循环从后往前扫描元素,借助栈的结构,倒着入栈,即正着出栈

package labuladong_learn.Data_structure;/**
 * Copyright (C), 2019-2021
 * author  candy_chen
 * date   2021/4/18 11:04
 *
 * @Classname nextBigElement
 * Description: 下一个更大元素I
 */

import java.util.Arrays;
import java.util.Stack;

/**
 * 输入一个数组,返回一个等长的数组,对应索引存储着下一个更大元素,如果没有更大的元素,就存 -1
 */
public class nextBigElement {
    public static int[] nextGreaterElement(int[] nums){
        int[] ans = new int[nums.length];  //存放答案的数组
        Stack<Integer> s = new Stack<>();
        for (int i = nums.length - 1; i >= 0 ; i--) {  //倒着往栈里放,其实就是正着出栈
            while (!s.isEmpty() && s.peek() <= nums[i]){ //判定个子高矮
                s.pop();  //矮个子出列,反正也被挡着了
            }
            ans[i] = s.isEmpty() ? -1 : s.peek();  //这个元素身后的第一个高个
            s.push(nums[i]);    //进队,接收之后的身高判定
        }
        return ans;
    }

    public static void main(String[] args) {
        System.out.println(Arrays.toString(nextGreaterElement(new int[]{2, 1, 2, 4, 3})));
    }
}

近几天的天气

package labuladong_learn.Data_structure;/**
 * Copyright (C), 2019-2021
 * author  candy_chen
 * date   2021/4/18 11:04
 *
 * @Classname nextBigElement
 * Description: 近几天的气温
 */

import java.util.Arrays;
import java.util.Stack;

/**
 *  计算对于每一天,至少还要等多少天才能等到一个更暖和的气温,如果等不到那一天就填 0
 *  输入T = [73,74,75,71,69,72,76,73] 算法应该返回 [1,1,4,2,1,1,0,0]
 */
public class nextBigElement_1 {
    public static int[] dailyTemperatures(int[] nums){
        int[] ans = new int[nums.length];
        Stack<Integer> s = new Stack<>();  //这里放索引,而不是元素
        for (int i = nums.length - 1; i >= 0; i--) {
            while (!s.empty() && nums[s.peek()] <= nums[i]){  //单调栈实现的原理关键点
                s.pop();
            }
            ans[i] = s.isEmpty() ? 0 : (s.peek() - i); // 得到索引间距
            s.push(i); //加入索引,而不是元素
        }
        return ans;
    }

    public static void main(String[] args) {
        System.out.println(Arrays.toString(dailyTemperatures(new int[]{73,74,75,71,69,72,76,73})));
    }
}

循环数组的下一个更大元素

package labuladong_learn.Data_structure;/**
 * Copyright (C), 2019-2021
 * author  candy_chen
 * date   2021/4/18 11:04
 *
 * @Classname nextBigElement
 * Description: 循环数组的下一个更大元素
 */

import java.util.Arrays;
import java.util.Stack;

/**
 *  给你一个数组,具有环形属性,
 *  输入[2,1,2,4,3]
 *  返回数组[4,2,4,-1,4]
 *  最后一个元素3绕了一圈后找到了比自己大的元素4
 */
public class nextBigElement_2 {

        /*
        模拟环形数组的效果,一般通过%运算符求模(余数),获得环形特效
         */
        /*
        int[] arr = {1,2,3,4,5};
        int n = arr.length,index = 0;
        while(true){
            print(arr[index]);
            index = (index + 1) % n;
        }
         */
        public static int[] nextGreaterElements(int[] nums){
            int n = nums.length;
            int[] res = new int[n];  //存放结果
            Stack<Integer> s = new Stack<>();
            //假装这个数组的长度翻倍了
            for(int i = 2 * n - 1;i >= 0;i--){
                while (!s.isEmpty() && s.peek() <= nums[i % n]){
                    s.pop();
                }
                //利用%求模防止索引越界
                res[i %n] = s.isEmpty() ? -1 : s.peek();
                s.push(nums[i % n]);
            }
            return res;
        }


    public static void main(String[] args) {
        System.out.println(Arrays.toString(nextGreaterElements(new int[]{73,74,75,71,69,72,76,73})));
    }
}

posted @ 2021-04-18 22:11  your_棒棒糖  阅读(33)  评论(0编辑  收藏  举报