参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

# 496.下一个更大元素 I [力扣题目链接](https://leetcode.cn/problems/next-greater-element-i/) 给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。 请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。 nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。 示例 1: 输入: nums1 = [4,1,2], nums2 = [1,3,4,2]. 输出: [-1,3,-1] 解释: 对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1 。 对于 num1 中的数字 1 ,第二个数组中数字1右边的下一个较大数字是 3 。 对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1 。 示例 2: 输入: nums1 = [2,4], nums2 = [1,2,3,4]. 输出: [3,-1] 解释: 对于 num1 中的数字 2 ,第二个数组中的下一个较大数字是 3 。 对于 num1 中的数字 4 ,第二个数组中没有下一个更大的数字,因此输出-1 。 提示: * 1 <= nums1.length <= nums2.length <= 1000 * 0 <= nums1[i], nums2[i] <= 10^4 * nums1和nums2中所有整数 互不相同 * nums1 中的所有整数同样出现在 nums2 中 # 思路 做本题之前,建议先做一下[739. 每日温度](https://programmercarl.com/0739.每日温度.html) 在[739. 每日温度](https://programmercarl.com/0739.每日温度.html)中是求每个元素下一个比当前元素大的元素的位置。 本题则是说nums1 是 nums2的子集,找nums1中的元素在nums2中下一个比当前元素大的元素。 看上去和[739. 每日温度](https://programmercarl.com/0739.每日温度.html) 就如出一辙了。 几乎是一样的,但是这么绕了一下,其实还上升了一点难度。 需要对单调栈使用的更熟练一些,才能顺利的把本题写出来。 从题目示例中我们可以看出最后是要求nums1的每个元素在nums2中下一个比当前元素大的元素,那么就要定义一个和nums1一样大小的数组result来存放结果。 一些同学可能看到两个数组都已经懵了,不知道要定一个一个多大的result数组来存放结果了。 **这么定义这个result数组初始化应该为多少呢?** 题目说如果不存在对应位置就输出 -1 ,所以result数组如果某位置没有被赋值,那么就应该是是-1,所以就初始化为-1。 在遍历nums2的过程中,我们要判断nums2[i]是否在nums1中出现过,因为最后是要根据nums1元素的下标来更新result数组。 **注意题目中说是两个没有重复元素 的数组 nums1 和 nums2**。 没有重复元素,我们就可以用map来做映射了。根据数值快速找到下标,还可以判断nums2[i]是否在nums1中出现过。 C++中,当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的。我在[关于哈希表,你该了解这些!](https://programmercarl.com/哈希表理论基础.html)中也做了详细的解释。 那么预处理代码如下: ```CPP unordered_map umap; // key:下标元素,value:下标 for (int i = 0; i < nums1.size(); i++) { umap[nums1[i]] = i; } ``` 使用单调栈,首先要想单调栈是从大到小还是从小到大。 本题和739. 每日温度是一样的。 栈头到栈底的顺序,要从小到大,也就是保持栈里的元素为递增顺序。只要保持递增,才能找到右边第一个比自己大的元素。 可能这里有一些同学不理解,那么可以自己尝试一下用递减栈,能不能求出来。**其实递减栈就是求右边第一个比自己小的元素了**。 接下来就要分析如下三种情况,一定要分析清楚。 1. 情况一:当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况 此时满足递增栈(栈头到栈底的顺序),所以直接入栈。 2. 情况二:当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况 如果相等的话,依然直接入栈,因为我们要求的是右边第一个比自己大的元素,而不是大于等于! 3. 情况三:当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况 此时如果入栈就不满足递增栈了,这也是找到右边第一个比自己大的元素的时候。 判断栈顶元素是否在nums1里出现过,(注意栈里的元素是nums2的元素),如果出现过,开始记录结果。 记录结果这块逻辑有一点小绕,要清楚,此时栈顶元素在nums2数组中右面第一个大的元素是nums2[i](即当前遍历元素)。 代码如下: ```CPP while (!st.empty() && nums2[i] > nums2[st.top()]) { if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素 int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标 result[index] = nums2[i]; } st.pop(); } st.push(i); ``` 以上分析完毕,C++代码如下:(其实本题代码和 [739. 每日温度](https://programmercarl.com/0739.每日温度.html) 是基本差不多的) ```CPP // 版本一 class Solution { public: vector nextGreaterElement(vector& nums1, vector& nums2) { stack st; vector result(nums1.size(), -1); if (nums1.size() == 0) return result; unordered_map umap; // key:下标元素,value:下标 for (int i = 0; i < nums1.size(); i++) { umap[nums1[i]] = i; } st.push(0); for (int i = 1; i < nums2.size(); i++) { if (nums2[i] < nums2[st.top()]) { // 情况一 st.push(i); } else if (nums2[i] == nums2[st.top()]) { // 情况二 st.push(i); } else { // 情况三 while (!st.empty() && nums2[i] > nums2[st.top()]) { if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素 int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标 result[index] = nums2[i]; } st.pop(); } st.push(i); } } return result; } }; ``` 针对版本一,进行代码精简后,代码如下: ```CPP // 版本二 class Solution { public: vector nextGreaterElement(vector& nums1, vector& nums2) { stack st; vector result(nums1.size(), -1); if (nums1.size() == 0) return result; unordered_map umap; // key:下标元素,value:下标 for (int i = 0; i < nums1.size(); i++) { umap[nums1[i]] = i; } st.push(0); for (int i = 1; i < nums2.size(); i++) { while (!st.empty() && nums2[i] > nums2[st.top()]) { if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素 int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标 result[index] = nums2[i]; } st.pop(); } st.push(i); } return result; } }; ``` 精简的代码是直接把情况一二三都合并到了一起,其实这种代码精简是精简,但思路不是很清晰。 建议大家把情况一二三想清楚了,先写出版本一的代码,然后在其基础上在做精简! ## 其他语言版本 Java ```java class Solution { public int[] nextGreaterElement(int[] nums1, int[] nums2) { Stack temp = new Stack<>(); int[] res = new int[nums1.length]; Arrays.fill(res,-1); HashMap hashMap = new HashMap<>(); for (int i = 0 ; i< nums1.length ; i++){ hashMap.put(nums1[i],i); } temp.add(0); for (int i = 1; i < nums2.length; i++) { if (nums2[i] <= nums2[temp.peek()]) { temp.add(i); } else { while (!temp.isEmpty() && nums2[temp.peek()] < nums2[i]) { if (hashMap.containsKey(nums2[temp.peek()])){ Integer index = hashMap.get(nums2[temp.peek()]); res[index] = nums2[i]; } temp.pop(); } temp.add(i); } } return res; } } // 版本2 class Solution { public int[] nextGreaterElement(int[] nums1, int[] nums2) { HashMap map = new HashMap<>(); for (int i = 0; i < nums1.length; i++) { map.put(nums1[i], i); } int[] res = new int[nums1.length]; Stack stack = new Stack<>(); Arrays.fill(res, -1); for (int i = 0; i < nums2.length; i++) { while (!stack.isEmpty() && nums2[stack.peek()] < nums2[i]) { int pre = nums2[stack.pop()]; if (map.containsKey(pre)) { res[map.get(pre)] = nums2[i]; } } stack.push(i); } return res; } } ``` Python3: ```python class Solution: def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]: result = [-1]*len(nums1) stack = [0] for i in range(1,len(nums2)): # 情况一情况二 if nums2[i]<=nums2[stack[-1]]: stack.append(i) # 情况三 else: while len(stack)!=0 and nums2[i]>nums2[stack[-1]]: if nums2[stack[-1]] in nums1: index = nums1.index(nums2[stack[-1]]) result[index]=nums2[i] stack.pop() stack.append(i) return result ``` Go: > 未精简版本 ```go func nextGreaterElement(nums1 []int, nums2 []int) []int { res := make([]int, len(nums1)) for i := range res { res[i] = -1 } m := make(map[int]int, len(nums1)) for k, v := range nums1 { m[v] = k } stack := []int{0} for i := 1; i < len(nums2); i++ { top := stack[len(stack)-1] if nums2[i] < nums2[top] { stack = append(stack, i) } else if nums2[i] == nums2[top] { stack = append(stack, i) } else { for len(stack) != 0 && nums2[i] > nums2[top] { if v, ok := m[nums2[top]]; ok { res[v] = nums2[i] } stack = stack[:len(stack)-1] if len(stack) != 0 { top = stack[len(stack)-1] } } stack = append(stack, i) } } return res } ``` > 精简版本 ```go func nextGreaterElement(nums1 []int, nums2 []int) []int { res := make([]int, len(nums1)) for i:= range res { res[i] = -1 } mp := map[int]int{} for i,v := range nums1 { mp[v] = i } // 单调栈 stack := []int{} stack = append(stack,0) for i:=1; i0 && nums2[i] > nums2[stack[len(stack)-1]] { top := stack[len(stack)-1] if _, ok := mp[nums2[top]]; ok { // 看map里是否存在这个元素 index := mp[nums2[top]]; // 根据map找到nums2[top] 在 nums1中的下标 res[index] = nums2[i] } stack = stack[:len(stack)-1] // 出栈 } stack = append(stack, i) } return res } ``` JavaScript: ```JS var nextGreaterElement = function (nums1, nums2) { let stack = []; let map = new Map(); for (let i = 0; i < nums2.length; i++) { while (stack.length && nums2[i] > nums2[stack[stack.length - 1]]) { let index = stack.pop(); map.set(nums2[index], nums2[i]); } stack.push(i); } let res = []; for (let j = 0; j < nums1.length; j++) { res[j] = map.get(nums1[j]) || -1; } return res; }; ``` TypeScript: ```typescript function nextGreaterElement(nums1: number[], nums2: number[]): number[] { const resArr: number[] = new Array(nums1.length).fill(-1); const stack: number[] = []; const helperMap: Map = new Map(); nums1.forEach((num, index) => { helperMap.set(num, index); }) stack.push(0); for (let i = 1, length = nums2.length; i < length; i++) { let top = stack[stack.length - 1]; while (stack.length > 0 && nums2[top] < nums2[i]) { let index = helperMap.get(nums2[top]); if (index !== undefined) { resArr[index] = nums2[i]; } stack.pop(); top = stack[stack.length - 1]; } if (helperMap.get(nums2[i]) !== undefined) { stack.push(i); } } return resArr; }; ``` Rust ```rust impl Solution { pub fn next_greater_element(nums1: Vec, nums2: Vec) -> Vec { let mut ans = vec![-1; nums1.len()]; use std::collections::HashMap; let mut map = HashMap::new(); for (idx, &i) in nums1.iter().enumerate() { map.insert(i, idx); } let mut stack = vec![]; for (idx, &i) in nums2.iter().enumerate() { while !stack.is_empty() && nums2[*stack.last().unwrap()] < i { let pos = stack.pop().unwrap(); if let Some(&jdx) = map.get(&nums2[pos]) { ans[jdx] = i; } } stack.push(idx); } ans } } ```