单调栈(每日温度)

每日温度

https://leetcode.cn/problems/daily-temperatures/description/
可以维护一个存储下标的单调栈,从栈底到栈顶的下标对应的温度列表中的温度依次递减。如果一个下标在单调栈里,则表示尚未找到下一次温度更高的下标。

正向遍历温度列表。对于温度列表中的每个元素 temperatures[i],如果栈为空,则直接将 i 进栈,如果栈不为空,则比较栈顶元素 prevIndex 对应的温度 temperatures[prevIndex] 和当前温度 temperatures[i],如果 temperatures[i] > temperatures[prevIndex],则将 prevIndex 移除,并将 prevIndex 对应的等待天数赋为 i - prevIndex,重复上述操作直到栈为空或者栈顶元素对应的温度小于等于当前温度,然后将 i 进栈。
上代码

点击查看代码
class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        stack<int>q;
        vector<int>ans(temperatures.size(),0);//初始化我的ans
        for(int i = 0; i < temperatures.size();i++)
        {
            while(!q.empty() && temperatures[q.top()]<temperatures[i])
            {//来判断我现在的温度是不是比我上次一的大
                ans[q.top()]=i-q.top();//是的话现在的温度减去我上次的高温
                q.pop();
            }
            q.push(i);//将我现在遍历的存进去
        }
        return ans;
    }
};

最大宽度坡

https://leetcode.cn/problems/maximum-width-ramp/description/
经过了早上的磨炼我觉得受益匪浅,对于这道题,我就以上午的思路来写这道题,因为咋一看也没有什么很大的区别感觉,就是求我j-i的最大值其中要满足的条件就是a[i]<a[j]和i<j
就是我只用左边和右边的比较其他不用管(这是我一开始的想法,结果就是狠狠地给我wa)无奈只求能去求助大佬的帮助。求助玩发现了并不是如此简单
解题正确思路:
我们既然想要j-i最大,那么我们就会希望j尽可能的大, i 尽可能的小,所以我们可以建立一个单调递减的栈来帮助我们寻找最大值,因为是单调递减的所以i->j之间会出现j比我现在的大而我只需要枚举我最大a[j]和我单调递减的a[i]的最大差值即可(也就是查到我最大的那个j将他与其他的进行比较看看能不能取到当i=0时的时候不行我在往下取取到最大)

点击查看代码
class Solution {
public:
    int maxWidthRamp(vector<int>& nums) {
        stack<int>q;//我开一个属于我的栈
        int ans=-1;//初始化我的ans,因为不管怎么样我的max都会比-1大所以我取-1
        q.push(0);//这样子可以将所有数进行判断,不会出现最后剩一个要单独判断 
        for(int i = 0; i < nums.size();i++)
        {
            if(nums[i]<nums[q.top()]||q.empty())q.push(i);
        }//这里是将我符合的单独拿出来,建立出单调递减的部分
        for(int i =nums.size()-1; i > 0;i--)
        {//从后往前拿来判断我当前的值是不是比我单调递减区间的最小值小
            while(!q.empty() && nums[i]>=nums[q.top()])
            {//是的话我就算出我们差值的最大值
                ans=max(i-q.top(),ans);
                q.pop();//将这个数删除,然后计算下一个的直到这个循环结束
            }
        }
        return ans;
    }
};

去除重复字母

https://leetcode.cn/problems/remove-duplicate-letters/
这道题看见重复的删掉第一个想法就是set一下,然后我在sort排序一下,就结束了,十分的ez,但是细看就是他要按原来的排序,删除掉重复的以后按原顺序最小的进行排序,这是什么意思?我没懂
题目解析
举个例子就是cbacdcbc这几个字母我c重复了许多但是我删掉后面的c就是cbad自言自语无非字典序是很大的,我需要按原排序最小也就是在我没删除重复的前,我需要再现有的几个c里面选择一个位置可以让我的字典序最小,像这道题我存在a,当a 为字典序开头时就是最小的,那么我看看能不能让a放在开头,如果不能那我在考虑第二小的,像这道题就是可以的我把c和b删除我后面还有bc所以可以删而a后面的c删不了因为删了就变成了ad,ad会比ac大而d我只有一个删不了所以不行
题目思路
1建两个表:一个表示字符表,一个用记录字符是否已添加的表
2)第一遍遍历字符串,用来建立字符表
3)第二遍遍历字符串,用来生成无重复字符串
然后开始遍历这个值会不会比我的尾巴这个值大大得话我就进行替换然后将原先的拿出来(前提是拿出来的后面还有多,可以把他再加回来)

点击查看代码
class Solution {
public:
    string removeDuplicateLetters(string s) {
        int len=s.size();//这个就不需要解释了
        bool vis[30];//用来判断现在26字母现在的状况
        int k[30];//用来判断一个字母存在几个
        string ans="";
        for(int i = 0; i < s.size(); i++)k[s[i]-'a']++;//每遍历到一个字母存下来
        for(int i = 0; i < s.size();i++)
        {
            if(!vis[s[i]-'a'])//判断这个字母有没有在我的栈里面
            {
                while(!ans.empty() &&ans.back()>s[i] && k[ans.back() - 'a'] > 0)
                {//假如我的栈目前的尾比现在我想放入的大,我就把我原先放入的删除
                    vis[ans.back()-'a']=0;
                    ans.pop_back();
                }
                ans.push_back(s[i]);//把我现在加入的这个进行记录
                 vis[s[i]-'a']=1;
            }
            k[s[i]-'a']--;//减去我消耗了的
        }
        return ans;
    }
};
posted @ 2024-07-23 17:06  糊涂不再糊涂  阅读(7)  评论(0编辑  收藏  举报