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

每日温度

代码随想录 (programmercarl.com)

暴力求法

        内外两层遍历数组,外层i表示返回的数组的下标,内层表示比当前i大的温度数组的下标。具体代码如下,会超时。

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        // 初始化一个和 temperatures 大小相同的向量 ans,所有值初始为0
        vector<int> ans(temperatures.size(), 0);
        // 遍历 temperatures 数组
        for (int i = 0; i < temperatures.size(); i++) {
            // 初始化 next 为0,用于记录需要等待的天数
            int next = 0;
            // 从当前元素之后开始遍历,寻找更高的温度
            for (int j = i + 1; j < temperatures.size(); j++) {
                // 每遍历一个元素,等待的天数加一
                next++;
                // 如果找到了一个更高的温度
                if (temperatures[j] > temperatures[i]) {
                    // 将等待的天数赋值给 ans 在当前位置的元素
                    ans[i] = next;
                    // 找到了更高的温度,跳出内层循环
                    break;
                }
            }
        }
        // 返回计算出的等待天数数组
        return ans;
    }
};

算法时间复杂度为O(n^2),空间复杂度为O(n)。

单调栈

想要更好了解单调栈,可以考虑看看下面的博客

算法数据结构——关于单调栈(Monotone Stack)的详细讲解及应用案例-CSDN博客

关于本题的单调栈解法

单调栈,你该了解的,这里都讲了!LeetCode:739.每日温度_哔哩哔哩_bilibili

单调栈记录遍历过的元素的下标

建议从左到右遍历元素

查找比当前元素大的元素使用单调递增栈,查找比当前元素小的元素使用单调递减栈

左侧查找看插入栈的栈顶元素,从右侧查找就看弹出栈时即将插入的元素。

本题查找下一个更大的元素,使用单调递增栈,创建一个ans数组。遍历数组元素时,比较栈顶索引和当前数组遍历索引的大小,若当前栈顶索引在数组中元素大于等于当前遍历的元素,将栈顶元素值i在ans数组中的值变为遍历的元素索引减去i.

ans[i] = current - i;

当栈非空时且栈顶索引的元素大于当前遍历元素时,继续,否则将当前遍历的索引下标current传入单调栈中。

当当前栈顶索引在数组中元素小于当前遍历的元素时,直接入栈即可。

具体代码如下。

class Solution {
public:
    // dailyTemperatures 函数计算每个温度之后更高温度需要等待的天数
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        // 初始化一个栈,用于存储温度数组中的索引
        stack<int> stack;
        // 将第一个元素的索引推入栈中
        stack.push(0);
        // 初始化一个和 temperatures 大小相同的向量 ans,所有值初始为0
        vector<int> ans(temperatures.size(), 0);
        // 遍历 temperatures 数组,从索引1开始
        for (int i = 1; i < temperatures.size(); i++) {
            // 如果当前温度小于等于栈顶索引对应的温度
            if (temperatures[i] <= temperatures[stack.top()]) {
                // 将当前索引推入栈中
                stack.push(i);
            } else if (temperatures[i] > temperatures[stack.top()] && !stack.empty()) {
                // 如果当前温度大于栈顶索引对应的温度,且栈不为空
                // 循环直到栈为空或者当前温度不再大于栈顶索引对应的温度
                while (!stack.empty() && temperatures[i] > temperatures[stack.top()]) {
                    // 弹出栈顶元素
                    int pop = stack.top();
                    // 计算等待天数,并赋值给 ans 在栈顶索引位置的元素
                    ans[pop] = i - pop;
                    // 弹出栈顶元素
                    stack.pop();
                }
                // 将当前索引推入栈中
                stack.push(i);
            }
        }
        // 返回计算出的等待天数数组
        return ans;
    }
};

算法的时间复杂度和空间复杂度均为O(n)。

下一个更大元素I

496. 下一个更大元素 I - 力扣(LeetCode)

本题和上题类似,注意两点,一是求的下一个大于当前元素的元素,二考虑到元素各不相同且为了便于查找,考虑使用哈希表。具体代码如下。

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        // 初始化一个哈希表,用于存储nums2中每个元素的下一个更大元素
        unordered_map<int, int> hashmap;
        // 初始化一个和 nums1 大小相同的向量 ans,所有值初始为-1
        vector<int> ans(nums1.size(), -1);
        // 初始化一个栈,用于存储nums2的索引
        stack<int> stack;
        stack.push(0);
        // 遍历 nums2 数组
        for (int i = 0; i < nums2.size(); i++) {
            // 如果当前元素小于等于栈顶索引对应的元素
            if (nums2[i] <= nums2[stack.top()]) {
                // 将当前索引推入栈中
                stack.push(i);
            } else {
                // 如果当前元素大于栈顶索引对应的元素
                while (!stack.empty() && nums2[i] > nums2[stack.top()]) {
                    // 弹出栈顶元素
                    int pop = stack.top();
                    // 将当前元素作为栈顶元素的下一个更大元素存储在哈希表中
                    hashmap[nums2[pop]] = nums2[i];
                    // 弹出栈顶元素
                    stack.pop();
                }
                // 将当前索引推入栈中
                stack.push(i);
            }
        }
        // 清空栈,将剩余元素的下一个更大元素设置为-1
        while (!stack.empty()) {
            int pop = stack.top();
            hashmap[nums2[pop]] = -1;
            stack.pop();
        }
        // 遍历 nums1 数组,根据哈希表构建答案
        for (int i = 0; i < nums1.size(); i++) {
            ans[i] = hashmap[nums1[i]];
        }
        // 返回计算出的下一个更大元素的数组
        return ans;
    }
};

算法的时间复杂度为O(m+n),m、n分别为两个数组的长度,空间复杂度为O(m+n),组成分别为哈希表n、ans数组m和栈n。

下一个更大元素II

. - 力扣(LeetCode)

和第一题思路类似,但由于是可以循环查找,有三个点需要注意,

首先是遍历数组从0-2*nums.size()-1,其次对下标采取取模的操作进行栈的插入等操作,最后是本题求的是下一个大于当前元素的元素,所以不是ans数组中的不是下标,而是元素。

class Solution {
public:
    // nextGreaterElements 函数找到每个元素右边第一个比它大的元素
    vector<int> nextGreaterElements(vector<int>& nums) {
        // 获取数组的大小
        int n = nums.size();
        // 初始化一个和 nums 大小相同的向量 ans,所有值初始为-1
        vector<int> ans(nums.size(), -1);
        // 初始化一个栈,用于存储数组索引
        stack<int> st;
        // 将0推入栈中
        st.push(0);
        // 遍历 nums 数组,循环两次数组长度减一,模拟循环数组
        for (int i = 1; i < 2 * nums.size() - 1; i++) {
            // 计算循环数组的索引
            int index = i % n;
            // 如果当前元素小于等于栈顶索引对应的元素
            if (nums[index] <= nums[st.top()]) {
                // 将当前索引推入栈中
                st.push(index);
            } else {
                // 如果当前元素大于栈顶索引对应的元素
                while (!st.empty() && nums[index] > nums[st.top()]) {
                    // 弹出栈顶元素
                    int pop = st.top();
                    // 将当前元素赋值给 ans 在栈顶索引位置的元素
                    ans[pop] = nums[index];
                    // 弹出栈顶元素
                    st.pop();
                }
                // 将当前索引推入栈中
                st.push(index);
            }
        }
        // 返回计算出的下一个更大元素的数组
        return ans;
    }
};

算法的时间复杂度为O(n),空间复杂度也是O(n)。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值