[LeetCode] 496. Next Greater Element I 下一个较大的元素之一
You are given two integer arrays nums1
and nums2
both of unique elements, where nums1
is a 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, return -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.
Example 2:
Input: nums1 = [2,4], nums2 = [1,2,3,4] Output: [3,-1] Explanation: For number 2 in the first array, the next greater number for it in the second array is 3. For number 4 in the first array, there is no next greater number for it in the second array, so output -1.
Constraints:
1 <= nums1.length <= nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 104
- All integers in
nums1
andnums2
are unique. - All the integers of
nums1
also appear innums2
.
Follow up: Could you find an
O(nums1.length + nums2.length)
solution?
这道题给了一个数组,又给了该数组的一个子集合,让我们求集合中每个数字在原数组中右边第一个较大的数字。参考题目中给的例子,题意不难理解,既然这次难度标识为 Easy,想必不是一道太难的题。二话不说,先上无脑暴力搜索,遍历子集合中的每一个数字,然后在原数组中找到这个数字,然后向右遍历,找到第一个大于该数字的数即可,参见代码如下:
解法一:
class Solution { public: vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) { vector<int> res(findNums.size()); for (int i = 0; i < findNums.size(); ++i) { int j = 0, k = 0; for (; j < nums.size(); ++j) { if (nums[j] == findNums[i]) break; } for (k = j + 1; k < nums.size(); ++k) { if (nums[k] > nums[j]) { res[i] = nums[k]; break; } } if (k == nums.size()) res[i] = -1; } return res; } };
我们来对上面的方法稍做优化,用 HashMap 先来建立每个数字和其坐标位置之间的映射,那么在遍历子集合中的数字时,就能直接定位到该数字在原数组中的位置,然后再往右边遍历寻找较大数即可,参见代码如下:
解法二:
class Solution { public: vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) { vector<int> res(findNums.size()); unordered_map<int, int> m; for (int i = 0; i < nums.size(); ++i) { m[nums[i]] = i; } for (int i = 0; i < findNums.size(); ++i) { res[i] = -1; int start = m[findNums[i]]; for (int j = start + 1; j < nums.size(); ++j) { if (nums[j] > findNums[i]) { res[i] = nums[j]; break; } } } return res; } };
下面这种方法使用了 HashMap 和栈,但是这里的 HashMap 和上面的不一样,这里是建立每个数字和其右边第一个较大数之间的映射,没有的话就是 -1。遍历原数组中的所有数字,如果此时栈不为空,且栈顶元素小于当前数字,说明当前数字就是栈顶元素的右边第一个较大数,那么建立二者的映射,并且去除当前栈顶元素,最后将当前遍历到的数字压入栈。当所有数字都建立了映射,那么最后可以直接通过 HashMap 快速的找到子集合中数字的右边较大值,参见代码如下:
解法三:
class Solution { public: vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) { vector<int> res; stack<int> st; unordered_map<int, int> m; for (int num : nums) { while (!st.empty() && st.top() < num) { m[st.top()] = num; st.pop(); } st.push(num); } for (int num : findNums) { res.push_back(m.count(num) ? m[num] : -1); } return res; } };
类似题目:
参考资料:
https://leetcode.com/problems/next-greater-element-i
https://leetcode.com/problems/next-greater-element-i/discuss/97676/java-solution-with-hashmap