单调栈、单调队列

本文介绍了单调栈和单调队列这两种数据结构,并通过LeetCode的几道题目来阐述它们的使用场景。单调栈常用于求解柱状图中最大的矩形,而单调队列则在滑动窗口最大值问题中有很好的表现。在解决实际问题时,我们需要判断新元素是否能入栈或入队,并适时弹出栈顶或队尾元素,确保数据结构的单调性。此外,还展示了如何在满足特定条件的情况下找到最小子序列。
摘要由CSDN通过智能技术生成

单调栈、单调队列

单调栈、单调队列是在栈和队列的基础上加上单调结构的数据结构。如果一个元素入栈或入队,他会检查之前的元素,如果之前的元素不可能是答案的解,那么就弹出元素,使得当前元素入栈或入队。

例题

LeetCode 239 滑动窗口最大值

此题是单调队列,每次遇到一个元素,一直从队尾弹出,直到队尾元素大于该元素为止。还需要注意检查队头元素是否在区间内。

LeetCode 84 柱状图中最大的矩形

此题为单调栈,首先的思路是先计算每一个柱子能到达的左边的最远距离和右边的最远距离,然后在遍历一次数组即可。我们分两次计算,设置一个单调栈,从左向右遍历数组,如果碰见小于栈顶元素,那就弹出栈顶,当栈中的元素被某一个元素弹出的时候,就是最远距离。计算最右边界也是如此,处理边界的时候,我们可以设置哨兵节点,使最后的时候栈能保持空的状态。

CFG 102916G

长度为K的最小子序列,利用单调栈可以轻松实现,当栈顶元素能够被弹出的时候,需要满足一下条件:

  1. 剩余字符序列的长度能够满足所需要的K的长度
  2. 栈顶元素大于要插入的元素

int main()
{
    string s;
    int k;
    cin >> s >> k;

    stack<char> sta;
    for (int i = 0; i < s.size(); i++)
    {
        while (!sta.empty() && sta.top() > s[i] && sta.size() - 1 + s.size() - i >= k)
        {
            sta.pop();
        }
        if (sta.size() < k)
            sta.push(s[i]);
    }

    string ans;
    while (!sta.empty())
    {
        ans.push_back(sta.top());
        sta.pop();
    }
    reverse(ans.begin(), ans.end());
    return ans;
    return 0;
}

LeetCode 5893

此题除了要求长度为K,还要求至少包含m个目标字符,也可以使用单调栈,只不过多加一个剩余字符序列的包含的目标字符能满足m个目标字符即可,以及何时才能加入字符。


class Solution
{
	public:
		string smallestSubsequence(string s, int k, char letter, int repetition)
		{
			vector<int> cnt(s.size() + 1);
			for(int i = s.size() - 1; i >= 0; i--)
			{
				cnt[i] += cnt[i + 1] + (s[i] == letter);
			}

			stack<char> sta;
			int req = 0;
			for(int i = 0; i < s.size(); i++)
			{
				while(!sta.empty() && sta.top() > s[i] && int(sta.size() ) - 1 + int(s.size() ) - i >= k
				        && req - (sta.top() == letter) + cnt[i] >= repetition)
				{
					if(sta.top() == letter) req--;
					sta.pop();
				}
				if(sta.size() < k && repetition - (req + (s[i] == letter)) <= k - int(sta.size()) - 1)
				{
					sta.push(s[i]);
					if(s[i] == letter) req++;
				}
			}

			string ans;

			while(!sta.empty())
			{
				ans.push_back(sta.top());
				sta.pop();
			}

			reverse(ans.begin(),ans.end());

			return ans;
		}
};

// TODO LIST

  1. LC739. Daily Temperatures
  2. LC862. Shortest Subarray with Sum at Least K
  3. LC901. Online Stock Span
  4. LC907. Sum of Subarray Minimums
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值