496. 下一个更大元素 I

74 阅读1分钟

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

题解:

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var nextGreaterElement = function (nums1, nums2) {
    // // 方法一:暴力法
    const n = nums1.length, m = nums2.length;
    const ans = []
    for (let i = 0; i < n; i++) {
        // 获取当前数在nums2中位置
        let j = nums2.indexOf(nums1[i])
        // 获取下一位置
        let k = j + 1
        // 下一位置小于nums2 并且下一位置的值小于当前位置值时
        // 遍历寻找大于当前位置值得数
        while (k < m && nums2[k] < nums2[j]) {
            ++k
        }
        // 当找不到大于前位置值的时取-1
        ans[i] = k < m ? nums2[k] : -1;
    }
    // return ans;
    // 方法二:单调栈
    // 1、创建一个临时栈,一个哈希表,然后遍历 nums2。
    // 2、若当前栈无数据,则当前数字入栈备用。
    // 3、若当前栈有数据,则用当前数字与栈顶比较:
    // 3.1 当前数字 > 栈顶,代表栈顶对应下一个更大的数字就是当前数字,
    // 则将该组数字对应关系,记录到哈希表。
    // 3.2 当前数字 < 栈顶,当前数字压入栈,供后续数字判断使用。
    // 4、这样,我们就可以看到哈希表中存在部分 nums2 数字的对应关系了,
    // 而栈中留下的数字,代表无下一个更大的数字,我们全部赋值为−1 ,然后存入哈希表即可。
    // 5、遍历 nums1,直接询问哈希表拿对应关系即可。
    let map = new Map(), stack = [], ans = [];
    nums2.forEach(item => {
        while (stack.length && item > stack[stack.length - 1]) {
            map.set(stack.pop(), item)
        };
        stack.push(item);
    });
    stack.forEach(item => map.set(item, -1));
    nums1.forEach(item => ans.push(map.get(item)));
    return ans;
};