算法初探LeetCode-下一个更大元素 I

107 阅读1分钟

LeetCode496-下一个更大元素 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]<=1040 <= nums1[i], nums2[i] <= 10^4
  • nums1nums2中所有整数 互不相同
  • nums1 中的所有整数同样出现在 nums2 中

思路分析

借助的是栈的结构,倒着入栈,其实是正着出栈。while 循环是把两个“高个”元素之间的元素排除,(这里解释就是,如果有一个再他们之间,就不符合逻辑本身了。)因为它的存在没有意义,前面挡着个“更高”的元素,所以他们不可能被作为后续进来的元素的 Next Great Number 了。

在题目中,要求得是其子集问题,需要的是下标。那么因此有两个办法。

采用Map,上图中人物下面的下标和next greater number,建立一个映射。如果你是现在建立的数组是[1,2,4]可以通过查1的映射为2,2的为4,4的为-1.快速的将建立数组[2,4,-1]题目就立马解决了 不采用映射,而是在题目中引入下标。但是也需要建立存储关系,所以这里要学会用Map。

算法代码

public int[] nextGreaterElement(int[] nums1, int[] nums2) {
    HashMap < Integer, Integer > pairs = new HashMap < > ();
    Deque < Integer > stack = new ArrayDeque < > ();
    //这一步要先去后入栈,去找数值大的,也就是排队问题,身高高的进栈,如果你看到你下面比的身高高,你要出栈
    for (int i = nums2.length - 1; i >= 0; i--) {
        int num = nums2[i];
        while (!stack.isEmpty() && stack.peek() <= num) {
            stack.pop();
        }
        //此时注意了,由于是去了nums1,是一个子集,所以可能会有包含这个对应的i的元素。
        //假设nums1[j]=nums[i],那么此时就要做一个映射,保留当前值。
        //这里如果不清楚可以看上面的图解。
        pairs.put(num, stack.isEmpty() ? -1 : stack.peek()); // 第一个是当前值Num,value的值可以这么理解,如果此时空栈,说明找不到右边比他大的数了,赋值-1,如果不是空栈,按照个算法逻辑,那么栈顶的元素,肯定是比我们当前元素大的,并且肯定是下次第一个比他大的。
        stack.push(num); //此时才入栈,那么接来下我也要接受别人的审判,如果左边的值都比此时Num大,要继续出栈,重复操作。
    }
    int ans[] = new int[nums1.length];
    for (int i = 0; i < nums1.length; i++) {
        ans[i] = pairs.get(nums1[i]);
    }
    return ans;
}

结果详情

Snipaste_2023-05-05_23-29-42.png

算法复杂度

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!