首页 > 编程语言 >「代码随想录算法训练营」第四十一天 | 单调栈 part1

「代码随想录算法训练营」第四十一天 | 单调栈 part1

时间:2024-08-19 16:57:57浏览次数:6  
标签:int 元素 随想录 st 第四十一 part1 vector ans nums2

739. 每日温度

题目链接:https://leetcode.cn/problems/daily-temperatures/
文章讲解:https://programmercarl.com/0739.每日温度.html
题目难度:中等
视频讲解:https://www.bilibili.com/video/BV1my4y1Z7jj/
题目状态:看题解

思路:

定义一个单调栈,该栈存放下标,规则是要保持其下标对应的温度值从栈底到栈头是单调递减的。再定义一个和题目数组大小相等的数组ans存放结果,初始化为0。具体步骤如下:

  1. 先将第一个元素的下标存入栈中。
  2. 循环遍历温度数组:
    • 若当前温度小于等于栈头元素的温度,将当前温度的下标压入栈。
    • 若当前温度大于栈头元素的温度,将栈中比当前温度低的元素都弹出,在弹出的时候将其压入结果数组中(i-st.top()),直到栈头大于当前温度,将当前温度的下标压入栈。
  3. 遍历结束后,返回结果数组。

代码:

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        int len = temperatures.size();
        stack<int> st;
        vector<int> ans(len, 0);
        st.push(0);
        for(int i = 1; i < len; ++i) {
            if(temperatures[i] <= temperatures[st.top()]) st.push(i);
            else {
                while(!st.empty() && temperatures[i] > temperatures[st.top()]) {
                    ans[st.top()] = i - st.top();
                    st.pop();
                }
                st.push(i);
            }
        }
        return ans;
    }
};

496. 下一个更大元素 I

题目链接:https://leetcode.cn/problems/next-greater-element-i/
文章讲解:https://programmercarl.com/0496.下一个更大元素I.html
题目难度:简单
视频讲解:https://www.bilibili.com/video/BV1jA411m7dX/
题目状态:用其他方法过的,看题解学习一下单调栈的方法

思路一:嵌套循环

非常传统的方法,遍历整个nums1,每遍历一个元素就在nums2中找到对应的元素下标,然后再在nums2中从下标位置开始向后遍历,直到找到一个比元素大的元素,将其值填入结果数组中并跳出循环,若找不到直接返回,因为这个结果数组初始化的时候将其全部值初始化为-1了。

代码一:

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        int len1 = nums1.size(), len2 = nums2.size();
        vector<int> ans(len1, -1);
        for(int i = 0; i < len1; ++i) {
            auto it = find(nums2.begin(), nums2.end(), nums1[i]);
            int index = distance(nums2.begin(), it);
            for(int j = index; j < len2; ++j) {
                if(nums2[j] > nums1[i]) {
                    ans[i] = nums2[j];
                    break;
                }
            }
        }
        return ans;
    }
};

消耗:
image

思路二:单调栈

nums1压入一个unordered_map<int, int>中,主要原因是它的查询和增删效率是最优的。
然后维护一个单调栈st,这个栈从栈底到栈头是单调递减的,用来遍历nums2,当遇到元素比栈头元素大的时候,就判断一下栈头元素是否在nums1中存在,如果存在就表示其后面有比栈头元素高的元素,将这个元素值更新到结果数组中。

代码二:

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        int len1 = nums1.size(), len2 = nums2.size();
        stack<int> st;
        vector<int> ans(len1, -1);
        if(len1 == 0) return ans;
        unordered_map<int, int> umap;
        for(int i = 0; i < len1; ++i) {
            umap[nums1[i]] = i; // key:下标元素,value:下标
        }
        // 将nums2压入单调栈
        st.push(0);
        for(int i = 1; i < len2; ++i) {
            if(nums2[i] <= nums2[st.top()]) st.push(i);
            else {
                while(!st.empty() && nums2[i] > nums2[st.top()]) {
                    if(umap.count(nums2[st.top()]) > 0) { // 看看umap中是否存在该元素
                        int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()]在nums1中的下标
                        ans[index] = nums2[i];
                    }
                    st.pop();
                }
                st.push(i);
            }
        }
        return ans;
    }
};

消耗:

image

503. 下一个更大元素 II

题目链接:https://leetcode.cn/problems/next-greater-element-ii/
文章讲解:https://programmercarl.com/0503.下一个更大元素II.html
题目难度:中等
视频讲解:https://www.bilibili.com/video/BV15y4y1o7Dw/
题目状态:自己的思路没通过,好奇怪,chatGPT帮忙修改了一下,直接把我思路改了

思路:

  1. 循环数组处理

    • 为了模拟循环数组,我们遍历数组两次。这样可以确保每个元素都能找到它的下一个更大元素,即使这个元素在数组的末尾。
  2. 使用栈

    • 栈用来存储索引,而不是元素值。这使我们能够直接在结果数组中更新对应位置的值。
  3. 遍历数组

    • 在每次遍历中,我们检查当前元素是否大于栈顶元素对应的值。
    • 如果是,则更新结果数组中栈顶元素索引对应的值,并弹出栈顶。
    • 如果当前索引在数组的前半部分(即小于 len),我们将其索引压入栈中。
  4. 结果更新

    • 通过这种方式,所有元素的下一个更大元素都会在结果数组中被正确更新。

代码:

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        int len = nums.size();
        stack<int> st;
        vector<int> ans(len, -1);
        for(int i = 0; i < 2 * len; ++i) {
            int num = nums[i % len];
            while(!st.empty() && nums[st.top()] < num) {
                ans[st.top()] = num;
                st.pop();
            }
            if(i < len) st.push(i);
        }
        return ans;
    }
};

消耗:

image

标签:int,元素,随想录,st,第四十一,part1,vector,ans,nums2
From: https://www.cnblogs.com/frontpen/p/18360373

相关文章

  • 代码随想录day34 || 62 不同路径,63 不同路径||,343整数拆分,96 不同搜索二叉树
    不同路径funcuniquePaths(mint,nint)int{ //dp五部曲 //dp数组以及下标的含义dp[i][j]代表从0,0走到i,j的不同路径条数 //递推公式 dp[i][j]=dp[i-1][j]+dp[i][j-1] //dp数组的初始化dp[i][0]==dp[0][j]=1 //遍历顺序 外层按照行,内层按照列遍历......
  • day46-dynamic programming-part13-8.17
    tasksfortoday:1.647.回文子串2.516.最长回文子序列--------------------------------------------------------------------1.647.回文子串Inthispractice,itisimportanttofigureouttheessencetodecideifastringatargetone,thestring[i,j]is......
  • 代码随想录Day18
    530.二叉搜索树的最小绝对差给你一个二叉搜索树的根节点root,返回树中任意两不同节点值之间的最小差值。差值是一个正数,其数值等于两值之差的绝对值。示例1:输入:root=[4,2,6,1,3]输出:1示例2:输入:root=[1,0,48,null,null,12,49]输出:1提示:树中节点的数目范围是......
  • 代码随想录算法训练营第11天|二叉树part01
    理论基础需要了解二叉树的种类,存储方式,遍历方式以及二叉树的定义二叉树纯理论方面还是比较简单,以前都学过,没什么可讲的。满二叉树就是满了,完全二叉树就是层满了(而且是左边)。平衡二叉搜索树就是左右深度绝对值差1。一般采用链式存储方式,顺序存储结构如果父节点的数组......
  • 代码随想录算法训练营第10天|栈与队列part02
    150.逆波兰表达式求值本题不难,但第一次做的话,会很难想到,所以先看视频,了解思路再去做题classSolution{public:intevalRPN(vector<string>&tokens){stack<longlong>st;for(conststring&token:tokens){if(token=="+......
  • 代码随想录Day17
    654.最大二叉树给定一个不重复的整数数组nums。最大二叉树可以用下面的算法从nums递归地构建:创建一个根节点,其值为nums中的最大值。递归地在最大值左边的子数组前缀上构建左子树。递归地在最大值右边的子数组后缀上构建右子树。返回nums构建的最大二叉树......
  • 【代码随想录训练营第42期 Day32打卡 - 从零开始动态规划 - LeetCode 509. 斐波那契数
    目录一、做题心得二、动规五步走三、题目与题解题目一:509.斐波那契数题目链接题解1:记忆性递归 题解2:动态规划题目二:70.爬楼梯 题目链接题解:动态规划题目三:746.使用最小花费爬楼梯题目链接题解:动态规划三、小结一、做题心得今天开始动态规划章节的第一......
  • 代码随想录算法训练营第十五天
    力扣题部分:110.平衡二叉树题目链接:.-力扣(LeetCode)题面:        给定一个二叉树,判断它是否是平衡二叉树        平衡二叉树 是指该树所有节点的左右子树的深度相差不超过1思路(递归):还是递归三部曲(关于三部曲的具体内容和对递归看法建议可见昨......
  • 代码随想录算法训练营第十八天
    力扣题部分:530.二叉搜索树的最小绝对差题目链接:.-力扣(LeetCode)题面:给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。差值是一个正数,其数值等于两值之差的绝对值。思路:    写关于二叉搜索树的问题,一定要先掌握二叉搜索树......
  • 代码随想录 day 54 字符串接龙 | 有向图的完全可达性 | 岛屿的周长
    字符串接龙字符串接龙解题思路利用每次更改一次的特性在字典中来找到符合条件的字符串,同时,我们利用set数据结构来筛选该字符串是否被访问过,同时记录到达该字符串所需要的路径长度知识点心得有向图的完全可达性有向图的完全可达性解题思路有向图和无向图的区别在于它的边......