【数据结构系列】单调栈
题目描述
输入一个数组,返回一个等长的数组,对应索引存储着下一个更大的元素,如果没有更大的元素,就存-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})));
}
}