单调栈:栈内元素保证递增或递减的
1、每日温度
2、下一个更大元素 I
3、下一个更大元素 II
给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。
使用单调栈主要有三个判断条件。
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
int[] res = new int[temperatures.length];
for(int i=1;i<temperatures.length;i++){
if(temperatures[i]<=temperatures[stack.peek()]){
stack.push(i);
}else{
while(!stack.isEmpty() && temperatures[i]>temperatures[stack.peek()]){
res[stack.peek()] = i-stack.peek();
stack.pop();
}
stack.push(i);
}
}
return res;
}
}
nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。
给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。
步骤:
1、先求出nums2[]数组的 res2【同每日温度中的res数组】
2、遍历nums1[]数组,在nums2数组当中找到值为 nums1[i] 的下标Index
3、找到该下标对应的res2值 res2[Index]
4、如果res2[Index] == 0 那么 res1[i] == -1
5、res2[Index]!=0 res1[i] = nums2[ res2[Index] +Index ];
【优化:可以使用map集合】
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
int[] resNum1 = new int[nums1.length];
int[] resNum2 = new int[nums2.length];
for(int j=1;j<nums2.length;j++){
if(nums2[j]<=nums2[stack.peek()]){
stack.push(j);
}else{
while(!stack.isEmpty() && nums2[j]>nums2[stack.peek()]){
resNum2[stack.peek()] = j-stack.peek();
stack.pop();
}
stack.push(j);
}
}
for(int i=0;i<nums1.length;i++){
int Index = findInNum2(nums1[i],nums2);
if(resNum2[Index]==0){
resNum1[i]=-1;
}else{
resNum1[i] = nums2[resNum2[Index]+Index];
}
}
return resNum1;
}
public int findInNum2(int target,int[] nums2){
for(int i=0;i<nums2.length;i++){
if(target==nums2[i]){
return i;
}
}
return 0;
}
}
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
int[] resNum1 = new int[nums1.length];
Arrays.fill(resNum1,-1);
HashMap<Integer,Integer> hashMap = new HashMap<>();
for(int i=0;i<nums1.length;i++){
hashMap.put(nums1[i],i);
}
for(int j=1;j<nums2.length;j++){
if(nums2[j]<=nums2[stack.peek()]){
stack.push(j);
}else{
while(!stack.isEmpty() && nums2[j]>nums2[stack.peek()]){
if(hashMap.containsKey(nums2[stack.peek()])){
Integer index = hashMap.get(nums2[stack.peek()]);
resNum1[index] = nums2[j];
}
stack.pop();
}
stack.push(j);
}
}
return resNum1;
}
}
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
分析:
重新定义一个数组:
nums = [1,2,1]
nums2 = [1,2,1,1,2,1];
然后再去求res数组
最后res只取原数组长度即可
class Solution {
public int[] nextGreaterElements(int[] nums) {
//拼接
int[] numsNew = new int[nums.length*2];
for(int i=0;i<nums.length;i++){
numsNew[i] = nums[i];
}
for(int i=nums.length;i<numsNew.length;i++){
numsNew[i] = nums[i-nums.length];
}
int[] res = new int[nums.length*2];
Arrays.fill(res,-1);
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
for(int i=1;i<numsNew.length;i++){
if(numsNew[i]<= numsNew[stack.peek()]){
stack.push(i);
}else{
while(!stack.isEmpty() && numsNew[i]>numsNew[stack.peek()]){
res[stack.peek()] = numsNew[i];
stack.pop();
}
stack.push(i);
}
}
int[] newRes = new int[nums.length];
for(int i=0;i<nums.length;i++){
newRes[i] = res[i];
}
return newRes;
}
}
分析
在原数组的基础上模拟成环的过程【取模】
class Solution {
public int[] nextGreaterElements(int[] nums) {
int[] res = new int[nums.length];
Arrays.fill(res,-1);
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
for(int i=1;i<nums.length*2;i++){
if(nums[i%nums.length]<= nums[stack.peek()]){
stack.push(i%nums.length);
}else{
while(!stack.isEmpty() && nums[i%nums.length]>nums[stack.peek()]){
res[stack.peek()] = nums[i%nums.length];
stack.pop();
}
stack.push(i%nums.length);
}
}
return res;
}
}