496. 下一个更大元素 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 。

提示:

nums1和nums2中所有元素是唯一的。 nums1和nums2 的数组大小都不超过1000。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/next-greater-element-i 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:

仔细一想,右边第一个大的值, 这不是跟 每日温度 一模一样吗,这道题的确是每日温度的变形

只不过用了两个数组, 需要一个 哈希表来存储遍历过完整数组的结果, 取值即可。

  • 此题目使用单调栈 + 哈希表解决

  • 因为nums1 包含于 nums2

  • 遍历 nums2,找到nums2中每个元素,的右边并且比其大的元素,并存入字典中

    • 找到 nums2 中每个元素,右边比其大的元素可以使用 单调栈(此题目使用单调递减栈)

      • 依次遍历nums2

        • while(stack不为空 并且 当前数字 > 栈顶数字){

          ​ 则 当前数字 就是栈顶数字 右边的第一个比其大的元素

          ​ map.put(stack.pop(), 当前数字)

          }

        • 跳出while循环后, 一定会满足 两个条件中的一个 (stack 为 空, 或者当前数字 < 栈顶数字)

          • 则将 当前数字入栈
      • 遍历完毕后, 则 nums2 中所有的元素, 其后边第一个大值都找到了

  • 而 nums1 包含与 nums2, 所以根据 map 就可以取出 nums1 在 nums2中 下一个比其大的值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
 *
 * 单调栈 + 哈希表
 * 利用单调递减队列
 *
 * 初始化一个 stack, 一个map<数字 : 右边第一个比其大的数字>
 * 遍历nums2
 *    while(当stack 不为空 并且 当前数字 > 栈顶数字)
 *          则当前数字就是栈顶数字右边第一个比其大的元素
 *          map.put(stack.pop(), 当前数字);
 *    当stack 为空   或者 当前数字 < 栈顶数字时(无重复数组,故没有 ==),  将当前数组入栈
 *  遍历完毕后, 则nums2中所有的元素,其后边第一个值都找到了
 *  而nums1 包含于 nums2. 所以根据map就可以取出 nums1在nums2中所有比其大的第一个元素
 *
 * */
public static int[] nextGreaterElement(int[] nums1, int[] nums2) {
    HashMap<Integer,Integer> map = new HashMap<>();
    Stack<Integer> stack = new Stack<>();
    for (int i = 0; i < nums2.length; i++) {
        int num = nums2[i];
        while (!stack.isEmpty() && num > stack.peek()){
            map.put(stack.pop(), num);
        }
        stack.push(num);
    }
    int[] res = new int[nums1.length];
    for (int i = 0; i < nums1.length; i++) {
        res[i] = -1;
        if (map.keySet().contains(nums1[i])){
            res[i] = map.get(nums1[i]);
        }
    }
    return res;
}

复杂度分析 :

时间复杂度 : O(m + n) (其中 m 为nums1的长度, n为num2的长度)

  • 遍历了nums1 和 nums2

空间复杂度 : O(n)

  • 使用了 跟 nums2容量一致的 map

推导过程

纸上模拟过程,有助于理解

WechatIMG347