问题描述
给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。
示例:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解题思路
解决此类问题我们可以使用单调栈的方式。
该问题实际可以简化为寻找:数组nums中每个数后第一个比当前数大的数字。于是我们可以考虑如下思路:
将nums[0]压入栈中,如果nums[1]>nums[0](栈顶元素),则视为找到了nums[0]后第一个比它大的数,然后将nums[0]出栈,nums[1]入栈,此时nums[1]成为栈顶元素。然后我们比较nums[1](栈顶元素)与nums[2]的大小,如果nums[1]>nums[2],则我们将nums[2]入栈,此时栈中有两个元素nums[2]为栈顶元素。此后遍历数组的过程中,比较栈顶元素与当前数组元素的大小:
1.栈顶元素>当前数组元素,则将当前数组元素入栈。
2.栈顶元素<当前数组元素,则将当前栈顶元素出栈,然后比较下一个栈顶元素与当前数组元素的大小,小于出栈,大于入栈,直至遍历完数组。
ps.当栈为空且数组未遍历完时,将当前数组元素入栈。栈中的遍历完数组后,栈中剩余元素意味者其后没有比其更大的元素。
我们可以使用HashMap以键值对的形式存储当前数组元素与其后第一个更大的元素。代码如下:
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
Stack<Integer> s=new Stack<>();
HashMap<Integer,Integer> m=new HashMap<>();
//结果集
int[] res=new int[nums1.length];
//循环数组
for(int i=0;i<nums2.length;i++){
//当前数组元素>栈顶元素,以键值对的形式存储
while(!s.isEmpty()&&nums2[i]>s.peek())
m.put(s.pop(),nums2[i]);
//当找到当前数组元素<栈顶元素,或栈空时压入元素
s.push(nums2[i]);
}
//栈中的遍历完数组后,栈中剩余元素意味者其后没有比其更大的元素
while(!s.isEmpty())
m.put(s.pop(),-1);
for(int i=0;i<res.length;i++){
res[i]=m.get(nums1[i]);
}
return res;
}
}