代码随想录算法训练营第五十天| 739. 每日温度、496.下一个更大元素 I、503.下一个更大元素II

739. 每日温度

在这里插入图片描述

题目链接: 739. 每日温度
文档讲解:代码随想录
状态:不会

思路:
这道题需要找到下一个更大元素。
使用栈来存储未找到更高温度的下标,那么栈中的下标对应的温度从栈底到栈顶是递减的。这意味着,栈顶元素的温度是当前温度数组中未找到更高温度的最高温度的下标。

总结成一句话就是:在解决“下一个更大元素”问题时,遍历数组时,如果当前元素大于栈顶元素,就先将栈顶元素出栈并更新其结果,然后将当前元素入栈。

题解:

    public int[] dailyTemperatures(int[] temperatures) {
        int n = temperatures.length;
        int[] res = new int[n];  // 初始化结果数组,长度与温度数组相同
        Deque<Integer> stack = new LinkedList<>();  // 初始化栈,用于存储未找到更高温度的下标

        for (int i = 0; i < n; i++) {  // 遍历温度数组
            // 如果当前温度高于栈顶元素的温度,则更新结果数组
            // 使用栈来存储未找到更高温度的下标,栈中的下标对应的温度从栈底到栈顶是递减的。
            // 这意味着,栈顶元素的温度是当前温度数组中未找到更高温度的最高温度的下标。
            while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peekLast()]) {
                int index = stack.pollLast();  // 弹出栈顶元素
                res[index] = i - index;  // 计算当前下标与栈顶元素下标的差值,并更新结果数组
            }
            stack.addLast(i);  // 将当前下标添加到栈中
        }

        return res;  // 返回结果数组
    }

496.下一个更大元素 I

在这里插入图片描述

题目链接: 496.下一个更大元素 I
文档讲解:代码随想录
状态:用的另一种方法

单调栈思路:

这题是属于找下一个更大元素,所以可以使用单调栈。

和每日温度类似,可以对nums2使用单调栈,即当前元素大于栈顶元素,就先将栈顶元素出栈并更新其结果,然后将当前元素入栈。但是这道题需要从nums2中找nums1元素,并且res的更新是按照nums1来的,所以可以将nums1中的元素存入哈希表中,如果nums2中遍历到的元素是nums1中的元素,则额外更新res。

题解:

    // 方法1: 暴力+哈希解法
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int[] res = new int[nums1.length];  // 结果数组
        HashMap<Integer, Integer> map = new HashMap<>();  // 存储 nums2 中元素的下标
        for (int i = 0; i < nums2.length; i++) {
            map.put(nums2[i], i);  // 将 nums2 中的元素及其下标放入 map 中
        }
        for (int i = 0; i < nums1.length; i++) {
            Integer index = map.get(nums1[i]);  // 获取 nums1 中元素在 nums2 中的下标
            for (int j = index; j < nums2.length; j++) {
                if (nums2[j] > nums1[i]) {  // 找到第一个比 nums1[i] 大的元素
                    res[i] = nums2[j];  // 更新结果数组
                    break;
                } else {
                    res[i] = -1;  // 未找到更大元素,默认设置为 -1
                }
            }
        }
        return res;
    }

    // 方法2: 单调栈
    public int[] nextGreaterElement2(int[] nums1, int[] nums2) {
        int[] res = new int[nums1.length];  // 结果数组
        Arrays.fill(res, -1);  // 初始化结果数组为 -1
        HashMap<Integer, Integer> map = new HashMap<>();  // 存储 nums1 中元素的下标
        Deque<Integer> stack = new LinkedList<>();  // 初始化单调栈
        for (int i = 0; i < nums1.length; i++) {
            map.put(nums1[i], i);  // 将 nums1 中的元素及其下标放入 map 中
        }
        for (int i = 0; i < nums2.length; i++) {
            // 如果当前元素 nums2[i] 大于栈顶元素,则更新栈顶元素在结果数组中的值
            while (!stack.isEmpty() && nums2[stack.peekLast()] < nums2[i]) {
                Integer num = nums2[stack.pollLast()];  // 弹出栈顶元素
                if (map.containsKey(num)) {
                    res[map.get(num)] = nums2[i];  // 更新结果数组中对应位置的值
                }
            }
            stack.addLast(i);  // 将当前元素下标加入栈中
        }
        return res;
    }

503.下一个更大元素II

在这里插入图片描述

题目链接: 503.下一个更大元素II
文档讲解:代码随想录
状态:磕磕绊绊

思路:
最直接的想法把两个数组拼接在一起,然后使用单调栈求下一个最大值。
优化的话在遍历的过程中模拟走了两边nums。

题解:

   public int[] nextGreaterElements(int[] nums) {
        int n = nums.length; // 获取数组的长度
        int[] res = new int[n]; // 结果数组,用来存储每个元素的下一个更大元素
        Arrays.fill(res, -1); // 初始化结果数组,默认值为-1
        Deque<Integer> stack = new LinkedList<>(); // 单调栈,用来存储数组元素的下标

        // 遍历2倍长度的数组,模拟循环数组
        for (int i = 0; i < 2 * n; i++) {
            // 如果当前元素大于栈顶元素,则更新栈顶元素在结果数组中的值
            while (!stack.isEmpty() && nums[i % n] > nums[stack.peekLast()]) {
                res[stack.pollLast()] = nums[i % n]; // 更新结果数组中对应下标的值
            }
            // 只将前n个元素的下标入栈
            if (i < n) {
                stack.addLast(i); // 将当前下标入栈
            }
        }
        return res; // 返回结果数组
    }
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值