每日一题:下一个更大元素 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 <= 1000
* 0 <= nums1[i], nums2[i] <= 10^4
* nums1和nums2中所有整数 互不相同
* nums1 中的所有整数同样出现在 nums2 中

进阶:

你可以设计一个时间复杂度为 O(nums1.length + nums2.length) 的解决方案吗?

思路

对于这类题目可以使用单调栈方法

该方法采用先行将 nums2 中的数字,对应的下一个更大的数字已经找出来,然后放到哈希表中,以供后面 nums1直接使用即可,我们这样做,可以将时间复杂度降到 n+m。

具体流程如下:

  • 创建一个临时栈,一个哈希表,然后遍历 nums2

  • 若当前栈无数据,则当前数字入栈备用。

  • 若当前栈有数据,则用当前数字与栈顶比较:

    • 当前数字 > 栈顶,代表栈顶对应下一个更大的数字就是当前数字,则将该组数字对应关系,记录到哈希表。
    • 当前数字 < 栈顶,当前数字压入栈,供后续数字判断使用。
  • 这样,就可以看到哈希表中存在部分 nums2 数字的对应关系了,而栈中留下的数字,代表无下一个更大的数字,全部赋值为 −1,然后存入哈希表即可。

  • 遍历 nums1,直接询问哈希表拿对应关系即可。

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int len1 = nums1.length;
        int len2 = nums2.length;
        Deque<Integer> deque =new ArrayDeque<>();
        HashMap<Integer, Integer> hashMap = new HashMap<>();
        for (int i = 0; i < len2; i++) {
            while (!deque.isEmpty() && deque.peekLast()<nums2[i]){
                hashMap.put(deque.removeLast(),nums2[i]);
            }
            deque.add(nums2[i]);
        }
        int[] res =new int[len1];
        for(int i=0;i<len1;i++){
            res[i] = hashMap.getOrDefault(nums1[i],-1);
        }
        return res;
    }
}