Leetcode 496 Next Greater Element
题目原文
You are given two arrays (without duplicates) nums1
and nums2
where nums1
’s elements are subset of nums2
. Find all the next greater numbers for nums1
's elements in the corresponding places of nums2
.
The Next Greater Number of a number x in nums1
is the first greater number to its right in nums2
. If it does not exist, output -1 for this number.
Example 1:
Input: nums1 = [4,1,2], nums2 = [1,3,4,2].
Output: [-1,3,-1]
Explanation:
For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1.
For number 1 in the first array, the next greater number for it in the second array is 3.
For number 2 in the first array, there is no next greater number for it in the second array, so output -1.
题意分析
给定一个数组nums1,它是nums2的的子集,输出nums1中每一个数在nums2中的下一个最大数。没有就输出-1.
解法分析
本题有三种解法,一种是动态规划,一种采用stack,一种为巧妙运用unorderd_map。本题不要纠结于两层循环就是O(n^2),要具体分析内层循环是否是常数。
动态规划
dp[i]表示nums[i]右边第一个大于它的元素,dp[i]=(nums[i]<nums[i+1])?nums[i+1]:max(dp[j],i<j<nums.size()-1).C++代码如下:
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
vector<int> dp(nums.size(),-1);
vector<int> res(findNums.size(),-1);
map<int,int> index;
if(nums.size()==0)
return res;
if(nums.size()==1){
res.push_back(-1);
return res;
}
dp[nums.size()-1]=-1;
int i,j;
for(i=0;i<findNums.size();i++)
index[findNums[i]]=i;
for(i=nums.size()-2;i>=0;i--){
if(nums[i]<nums[i+1])
dp[i]=nums[i+1];
else{
for(j=i+1;j<=nums.size()-1;j++){
if(nums[i]<dp[j]){
dp[i]=dp[j];
break;
}
}
if(j==nums.size())
dp[i]=-1;
}
if(index.count(nums[i]))
res[index[nums[i]]]=dp[i];
}
return res;
}
};
unordered_map
对nums建立值和下标的key-value对,外层循环遍历findNums,通过unordered_map找到对应的nums中的下标,从该下标开始搜索greater数,并记录下来。C++代码如下:
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
vector<int> res;
unordered_map<int,int> mp;
for(int i=0; i<nums.size(); i++) mp[nums[i]]=i;
for(int i=0; i<findNums.size(); i++){
int newval=-1;
for(int j=mp[findNums[i]]+1; j<nums.size(); j++){
if(findNums[i]<nums[j]) { newval=nums[j]; break; }
}
res.push_back(newval);
}
return res;
}
};
这种方法平均性能好。
stack
对于7,6,5,4,3,2,1,3这种情况,可以将递减序列存入stack中,遇到比栈顶元素大的元素a时,将stack中所有比a小的元素pop,并建立map,key为值,value为greater number,这种方法每个元素都最多被push和pop一次,所以复杂度为O(n)。java代码如下:
public int[] nextGreaterElement(int[] findNums, int[] nums) {
Map<Integer, Integer> map = new HashMap<>(); // map from x to next greater element of x
Stack<Integer> stack = new Stack<>();
for (int num : nums) {
while (!stack.isEmpty() && stack.peek() < num)
map.put(stack.pop(), num);
stack.push(num);
}
for (int i = 0; i < findNums.length; i++)
findNums[i] = map.getOrDefault(findNums[i], -1);
return findNums;
}