代码随想录第四十八天| 739. 每日温度 496.下一个更大元素 I 503.下一个更大元素II

739. 每日温度

力扣题目链接
请根据每日气温列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:气温列表长度的范围是 [1, 30000]。每个气温的值均为华氏度,都是在 [30, 100] 范围内的整数。

解题思路

我们可以使用一个栈来帮助我们解决这个问题。栈中存储的是气温列表中元素的索引,而不是气温值本身。我们从左到右遍历气温列表,对于每个元素,我们检查栈顶元素所对应的气温是否小于当前气温。如果是,那么我们就可以计算出需要等待的天数,并更新结果数组。我们将当前元素的索引压入栈中,以便后续元素可以使用它来计算等待天数。
以下是具体的步骤:

  1. 初始化一个结果数组 result,长度与气温列表相同,初始值均为 0。
  2. 使用一个栈 stack 来存储气温列表的索引。
  3. 遍历气温列表,对于每个元素:
    • 当栈不为空,且栈顶元素对应的气温小于当前气温时,弹出栈顶元素,并计算等待天数,更新结果数组。
    • 将当前元素的索引压入栈中。
  4. 遍历结束后,栈中剩余的索引对应的结果数组位置都是 0,因为之后不会有更高的气温。
    以下是具体的代码实现:
class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int[] result = new int[temperatures.length];
        Deque<Integer> stack = new LinkedList<>();
        stack.push(0);
        for (int i = 1; i < temperatures.length; i++) {
            while (!stack.isEmpty() && temperatures[stack.peek()] < temperatures[i]) {
                int index = stack.pop();
                result[index] = i - index;
            }
            stack.push(i);
        }
        return result;
    }
}

这个算法的时间复杂度是 O(N),因为每个元素最多只会被压入和弹出栈一次。空间复杂度也是 O(N),因为我们需要一个额外的数组来存储结果,以及一个栈来存储索引。

496. 下一个更大元素 I

力扣题目链接
给你两个 没有重复元素 的数组 nums1nums2 ,其中 nums1nums2 的子集。
请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 xnums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1

解题思路

我们可以使用单调栈来解决这个问题。单调栈是一种特殊的栈,用于解决一类特定的问题,即找到下一个更大元素、下一个更小元素等。
以下是解题步骤:

  1. 创建一个结果数组 result,初始化所有值为 -1,因为如果找不到更大的元素,则返回 -1
  2. 使用一个哈希表 hashMap 来存储 nums1 中每个元素的位置,以便我们可以快速更新 result 数组。
  3. 初始化一个栈 stack,用于存储 nums2 中元素的索引。
  4. 遍历 nums2,对于每个元素,如果当前元素大于栈顶元素对应的 nums2 中的值,那么我们就找到了栈顶元素在 nums2 中的下一个更大元素。我们将这个更大元素赋值给 result 数组中对应 nums1 的位置,并弹出栈顶元素。
  5. 如果当前元素不大于栈顶元素,则将其索引压入栈中。
  6. 继续遍历,直到 nums2 的所有元素都被处理。
    以下是具体的代码实现:
class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int[] result = new int[nums1.length];
        Arrays.fill(result, -1); // 初始化结果数组
        Deque<Integer> stack = new LinkedList<>(); // 初始化栈
        HashMap<Integer, Integer> hashMap = new HashMap<>(); // 初始化哈希表
        for (int i = 0; i < nums1.length; i++) {
            hashMap.put(nums1[i], i); // 存储nums1中元素的位置
        }
        stack.push(0); // 将nums2的第一个元素的索引压入栈中
        for (int i = 1; i < nums2.length; i++) {
            while (!stack.isEmpty() && nums2[stack.peek()] < nums2[i]) {
                if (hashMap.containsKey(nums2[stack.peek()])) {
                    Integer index = hashMap.get(nums2[stack.peek()]);
                    result[index] = nums2[i]; // 更新结果数组
                }
                stack.pop(); // 弹出栈顶元素
            }
            stack.push(i); // 将当前元素的索引压入栈中
        }
        return result;
    }
}

这个算法的时间复杂度是 O(M+N),其中 M 是 nums1 的长度,N 是 nums2 的长度。因为每个元素最多只会被压入和弹出栈一次。空间复杂度是 O(N),因为我们需要一个额外的数组来存储结果,以及一个栈和一个哈希表来存储索引和映射关系。

503. 下一个更大元素 II

力扣题目链接
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

解题思路

由于数组是循环的,我们可以通过将数组长度翻倍来模拟循环的效果。这样,我们可以使用单调栈来找到每个元素的下一个更大元素。
以下是解题步骤:

  1. 初始化一个结果数组 result,长度与输入数组 nums 相同,并将所有元素设置为 -1,因为如果找不到更大的元素,则返回 -1。
  2. 使用一个双端队列 stack 来作为栈,用于存储元素的索引。
  3. 遍历数组,由于是循环数组,我们将遍历的次数设置为 nums.length * 2,通过取余操作 i % nums.length 来模拟循环。
  4. 对于每个元素,如果当前元素大于栈顶元素对应的 nums 中的值,那么我们就找到了栈顶元素在 nums 中的下一个更大元素。我们将这个更大元素赋值给 result 数组中对应的位置,并将栈顶元素弹出。
  5. 将当前元素的索引压入栈中。
  6. 最后返回 result 数组。

代码实现

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int[] result = new int[nums.length];
        Arrays.fill(result, -1);
        Deque<Integer> stack = new LinkedList<>();
        stack.push(0);
        for (int i = 1; i < nums.length * 2; i++) {
            while (!stack.isEmpty() && nums[stack.peek()] < nums[i % nums.length]) {
                int index = stack.pop();
                result[index] = nums[i % nums.length];
            }
            stack.push(i % nums.length);
        }
        return result;
    }
}

这个算法的时间复杂度是 O(N),因为尽管我们遍历了两次数组,但每个元素最多只会被压入和弹出栈一次。空间复杂度是 O(N),因为我们需要一个额外的数组来存储结果,以及一个栈来存储索引。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值