LeetCode 496. Next Greater Element I
nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x ****大的元素。
给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。
对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1 。
返回一个长度为 nums1.length 的数组 **ans **作为答案,满足 **ans[i] **是如上所述的 下一个更大元素 。
示例 1:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释: nums1 中每个值的下一个更大元素如下所述:
- 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
- 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
- 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
示例 2:
输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释: nums1 中每个值的下一个更大元素如下所述:
- 2 ,用加粗斜体标识,nums2 = [1,2,3,4]。下一个更大元素是 3 。
- 4 ,用加粗斜体标识,nums2 = [1,2,3,4]。不存在下一个更大元素,所以答案是 -1 。
提示:
1 <= nums1.length <= nums2.length <= 10000 <= nums1[i], nums2[i] <= 104nums1和nums2中所有整数 互不相同nums1中的所有整数同样出现在nums2中
进阶: 你可以设计一个时间复杂度为 O(nums1.length + nums2.length) 的解决方案吗?
算法
(哈希表 + 单调栈) O(n)
首先将 nums2 里的所有元素存入 unordered_map 中,方便确定 nums1 中元素在 nums2 中的位置。
对 nums2 中的每个元素,需要求其右边第一个比其大的元素,这里可以用单调栈来实现。
建立一个单调递减的栈,如果新入栈的元素比栈顶元素值要大,则栈顶出栈,直到不比栈顶元素大为止。
栈顶出栈的过程中,就已经确定了其右边第一个比其大的元素就是最后要新入栈的元素。
时间复杂度
哈希表的时间复杂度为 O(n)
单调栈的时间复杂度为 O(n)
故总时间复杂度为 O(n)。
空间复杂度
需要额外 O(n) 的空间存储哈希表,单调栈等。
C++ 代码
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
int n = nums.size();
unordered_map\<int, int> hash;
for (int i = 0; i < n; i++)
hash\[nums\[i]] = i;
stack<int> st;
vector<int> greater(n);
for (int i = 0; i < n; i++) {
while (!st.empty() && nums[i] > nums[st.top()]) {
greater[st.top()] = nums[i];
st.pop();
}
st.push(i);
}
while (!st.empty()) {
greater[st.top()] = -1;
st.pop();
}
int m = findNums.size();
vector<int> ans(m);
for (int i = 0; i < m; i++)
ans[i] = greater[hash[findNums[i]]];
return ans;
}
};