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.
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.
Note:
- All elements in
nums1
andnums2
are unique. - The length of both
nums1
andnums2
would not exceed 1000.
這道題給了我們一個數組,又給了該數組的一個子集合,讓我們求集合中每個數字在原數組中右邊第一個較大的數字。參考題目中給的例子,題意不難理解,既然這次難度標識為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; } };
我們來對上面的方法稍做優化,我們用哈希表先來建立每個數字和其坐標位置之間的映射,那么我們在遍歷子集合中的數字時,就能直接定位到該數字在原數組中的位置,然后再往右邊遍歷尋找較大數即可,參見代碼如下:
解法二:
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; } };
下面這種方法使用了哈希表和棧,但是這里的哈希表和上面的不一樣,這里是建立每個數字和其右邊第一個較大數之間的映射,沒有的話就是-1。我們遍歷原數組中的所有數字,如果此時棧不為空,且棧頂元素小於當前數字,說明當前數字就是棧頂元素的右邊第一個較大數,那么建立二者的映射,並且去除當前棧頂元素,最后將當前遍歷到的數字壓入棧。當所有數字都建立了映射,那么最后我們可以直接通過哈希表快速的找到子集合中數字的右邊較大值,參見代碼如下:
解法三:
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