【LeetCode】第496题——下一个更大元素I(难度:简单)

【LeetCode】第496题——下一个更大元素I(难度:简单)

  • 题目描述
  • 解题思路
  • 代码详解
    • 思路一:暴力法
    • 思路二:单调栈(推荐)
  • 注意点

题目描述

给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。

请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。

nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。

  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. 示例 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] <= 104
nums1和nums2中所有整数 互不相同
nums1 中的所有整数同样出现在 nums2 中

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

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

解题思路

思路一:暴力法。双循环,外层循环遍历nums1的元素,内层循环遍历nums2的元素,找到下一个更大的元素后直接在答案数组的对应位置赋nums2的值,找不到就赋值-1。

思路二:单调栈,结合栈对象和HashMap对象。

何为单调栈?我们直接来举个例子吧,该例子包含了绝大多数操作情况。对于数组 [1, 3, 2, 4, 7, 5, 6, 9, 8] 来说:

  1. 数字1入栈,栈内{1}
  2. 因为3大于栈顶数字1,HashMap里{1:3},数字1出栈,栈内{},此时栈为空,数字3入栈,栈内{3}
  3. 因为2小于栈顶数字3,数字2入栈,栈内{3, 2}
  4. 因为4大于栈顶数字2,HashMap里{1:3, 2:4},数字2出栈,栈内{3},此时栈不为空,还是对数字4进行操作。因为4大于栈顶数字3,HashMap里{1:3, 2:4, 3:4},数字3出栈,栈内{},此时栈为空,数字4入栈,栈内{4}
  5. 因为7大于栈顶数字4,HashMap里{1:3, 2:4, 3:4, 4:7},数字4出栈,栈内{},此时栈为空,数字7入栈,栈内{7}
  6. 因为5小于栈顶数字7,数字5入栈,栈内{7, 5}
  7. 因为6大于栈顶数字5,HashMap里{1:3, 2:4, 3:4, 4:7, 5:6},数字5出栈,栈内{7},此时栈不为空,还是对数字6进行操作。因为6小于栈顶数字7,数字6入栈,栈内{7, 6}
  8. 因为9大于栈顶数字6,HashMap里{1:3, 2:4, 3:4, 4:7, 5:6, 6:9},数字6出栈,栈内{7},此时栈不为空,还是对数字9进行操作。因为9大于栈顶数字7,HashMap里{1:3, 2:4, 3:4, 4:7, 5:6, 6:9, 7:9},数字7出栈,栈内{},此时栈为空,数字9入栈,栈内{9}
  9. 因为8小于栈顶数字9,数字8入栈,栈内{9, 8}
  10. 此时数组内数字已完全遍历,但栈仍非空(若栈空则无视这一步),栈顶数字8出栈,HashMap里{1:3, 2:4, 3:4, 4:7, 5:6, 6:9, 7:9, 8:-1},栈顶数字9出栈,HashMap里{1:3, 2:4, 3:4, 4:7, 5:6, 6:9, 7:9, 8:-1, 9:-1}

直接用HashMap的get方法可以直接获取下一个更大元素

代码详解

思路一:暴力法

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int[] ints = new int[nums1.length];	// 答案数组
        // 外层循环遍历nums1
        for(int i = 0; i < nums1.length; ++i) {
            boolean isfound = false;	// 记录nums1的当前数字是否在nums2中被找到
            ints[i] = -1;	// 先将此位设置为-1
            // 内层循环遍历nums2
            for(int j = 0; j < nums2.length; ++j) {
            	// 未在nums2中找到与nums1当前数字相同的数字时,继续往后遍历寻找
                if(!isfound) {
                    if(nums1[i] == nums2[j]) {
                        isfound = true;
                    }
                // 找到后,再找下一个更大的元素
                } else {
                    if(nums2[j] > nums1[i]) {
                        ints[i] = nums2[j];
                        break;
                    }
                }
            }
        }
        return ints;
    }
}

思路二:单调栈(推荐)

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int[] ints = new int[nums1.length];	// 答案数组
        HashMap<Integer, Integer> hs = new HashMap<>();
        Stack<Integer> stack = new Stack<>();
        for(int i = 0; i < nums2.length; ++i) {
            if(stack.isEmpty()) {	// 如果栈为空,直接放入
                stack.push(nums2[i]);
            } else {
                while((!stack.isEmpty()) && nums2[i] > stack.peek()) {	// 如果栈不为空,,则nums2当前数字与栈顶数字一一比较,大于栈顶数字的出栈并放入HashMap中,小于栈顶数字则直接入栈
                    hs.put(stack.pop(), nums2[i]);
                }
                stack.push(nums2[i]);
            }
        }
        // 将栈内残余数字一一出栈,因为无下一个更大元素,因此HashMap的value均为-1
        while(!stack.isEmpty()) {
            hs.put(stack.pop(), -1);
        }
        // 用.get()方法为答案数组ints中的各个位置赋值
        for(int i = 0; i < ints.length; ++i) {
            ints[i] = hs.get(nums1[i]);
        }
        return ints;
    }
}

注意点

  • 暴力法的时间复杂度为 O(nums1.length × nums2.length),单调栈的时间复杂度为 O(nums1.length + nums2.length),而且实现起来并不复杂,用空间换时间,因此推荐单调栈思路。

你可能感兴趣的:(LeetCode题解,leetcode,java,暴力法,单调栈)