• 代码随想录 11.18 || 单调栈 LeetCode 739.每日温度、496.下一个更大的元素Ⅰ


    单调栈

            单调栈,即栈中存储的元素值单调递增 or 递减,通常用于在一维数组中寻找任意位置元素的右边或者左边第一个更 大 / 小 元素的位置。在遍历过程中,使用单调栈记录遍历过的元素,栈中存放的是元素的下标,而并非元素本身。

    739.每日温度

         给定一个整数数组 temperatures,表示每天的温度,返回一个数组 answer,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。计算一维数组 temperatures 中每一个元素与右边第一个最大的元素的距离。

           使用单调栈存储遍历过元素的下标,在遍历过程中可分为三种情况:当前访问元素大于、小于和等于栈顶元素,对应着不同的处理。

            当前访问元素 temperatures[i] > st.top(),说明我们找到了对应 st.top() 为下表的元素右边第一个最大值,temperatures[i]。根据题意要求,结果集中存储的是右边第一个更大元素到该元素的距离,因此 result[st.top()] = i - st.top(),并将栈顶元素出栈。注意,当前访问的元素,可能比栈不止一个元素都大,即它可能是多个元素的右边第一个最大的元素,所以需要使用一个循环进行遍历。直至不符合要求或者栈空,然后将当前元素压栈。从上述操作可以看出,栈顶元素为即将要加入结果集的元素的下标,当前访问的元素为可能符合要求的元素。

            当前访问元素 temperatures[i] < st.top(),说明当前元素不符合要求,直接将当前元素压栈,相等情况同理。

    1. class Solution {
    2. public:
    3. vector<int> dailyTemperatures(vector<int> &T) {
    4. int len = T.size();
    5. auto result = vector<int> (len, 0);
    6. stack<int> st;
    7. st.push(0);
    8. for (int i = 1; i < len; ++i) {
    9. if (T[i] <= T[st.top()]) st.push(i);
    10. else {
    11. while (!st.empty() && T[i] > T[st.top()]) {
    12. result[st.top()] = i - st.top();
    13. st.pop();
    14. }
    15. st.push(i);
    16. }
    17. }
    18. return result;
    19. }
    20. };

             下面是精简过后的代码。

    1. class Solution {
    2. public:
    3. vector<int> dailyTemperatures(vector<int> &T) {
    4. int len = T.size();
    5. vector<int> result(len, 0);
    6. stack<int> st;
    7. for (int i = 0; i < len; ++i) {
    8. while (!st.empty() && T[i] > T[st.top()]) {
    9. result[st.top()] = i - st.top();
    10. st.pop();
    11. }
    12. st.push(i);
    13. }
    14. return result;
    15. }
    16. };

    496.下一个更大的元素Ⅰ

        题干过于复杂,不在此赘述。本题为单调栈经典题目,设有一些变化。数组 nums1 是 nums2 的子集,寻找 num1 中的元素,在 nums2 中右边第一个更大的元素。

            首先是暴力解法,居然通过了,嵌套三个循环,第一个循环用于在 nums1 中挑选元素,第二个循环用于在 nums2 中寻找给定元素的位置,第三个循环用于返回给定元素右起第一个更大的值。在实现上是三层嵌套循环,但是本质上为两层嵌套循环,第三层循环只执行了一次。

    1. class Solution {
    2. public:
    3. vector<int> nextGreaterElement(vector<int> &nums1, vector<int> &nums2) {
    4. int len1 = nums1.size(), len2 = nums2.size();
    5. vector<int> result(len1, -1);
    6. for (int i = 0; i < len1; ++i) {
    7. for (int j = 0; j < len2; ++j) {
    8. if (nums2[j] != nums1[i]) continue;
    9. for (int k = j + 1; k < len2; ++k) {
    10. if (nums2[k] > nums1[i]) {
    11. result[i] = nums2[k];
    12. break;
    13. }
    14. }
    15. break;
    16. }
    17. }
    18. return result;
    19. }
    20. };

            单调栈解法,nums1 是 nums2 的子集,那么只要找到 nums2 中所有元素右边第一个更大的元素的值,然后判断该元素在不在 nums1 中,如果在将这个更大的值添加进结果集即可。问题转化为单调栈 + 哈希映射的使用。下面的代码可以如 739.每日温度 进行精简。

    1. class Solution {
    2. public:
    3. vector<int> nextGreaterElement(vector<int> &nums1, vector<int> &nums2) {
    4. int len1 = nums1.size(), len2 = nums2.size();
    5. vector<int> result(len1, -1);
    6. if (len1 == 0) return result;
    7. unordered_map<int, int> umap;
    8. for (int i = 0; i < len1; ++i) umap[nums1[i]] = i;
    9. stack<int> st;
    10. st.push(0);
    11. for (int i = 1; i < len2; ++i) {
    12. if (nums2[i] < nums2[st.top()]) st.push(i);
    13. else if (nums2[i] == nums2[st.top()]) st.push(i);
    14. else {
    15. while (!st.empty() && nums2[i] > nums2[st.top()]) {
    16. if (umap.count(nums2[st.top()]) > 0) {
    17. int index = umap[nums2[st.top()]];
    18. result[index] = nums2[i];
    19. }
    20. st.pop();
    21. }
    22. st.push(i);
    23. }
    24. }
    25. return result;
    26. }
    27. };

  • 相关阅读:
    关于我有一个后台可配置blog的系统,我使用nuxt做了一个网站,后台可以更新文章这件事情
    uniapp-vue3-vite 搭建小程序、H5 项目模板
    golang学习笔记——switch 判断语句
    Linux操作系统的内存使用方法详细解析
    如何打造一个可躺赚的网盘项目,每天只需要2小时
    数字政府应用场景中数据安全体系
    PDF格式分析(七十五)——线型注释(Line)
    【查找重复代码】python实现-附ChatGPT解析
    【代码随想录】算法训练营 第十天 第五章 栈与队列 Part 1
    编译原理网课笔记——第二章
  • 原文地址:https://blog.csdn.net/weixin_73177736/article/details/134488863