单调栈算法

单调栈算法

单调栈算法是一种用于解决区间最值问题的算法,它通过将待求解的区间不断缩小,最终得到区间的最值。本文将详细介绍单调栈算法的原理、流程以及C++代码实现,并给出一个例题及题解。

原理

单调栈算法的基本思想是:从待求解的区间两端开始,通过比较两个元素的大小关系,将较大的元素弹出栈,较小的元素入栈,这样不断地进行操作,直到区间被缩减到只包含一个元素为止。此时,该元素就是区间的最值。

为了保证单调性,我们需要定义一个栈来存储待比较的元素。当栈顶元素小于等于新加入的元素时,说明区间已经不再单调递增或递减,此时需要将栈顶元素弹出。反之,则将新元素入栈。

算法流程

  1. 初始化一个空栈stack和一个变量maxValue,用于存储当前找到的最大值。
  2. 将待求解的区间的起始元素入栈。
  3. 当栈不为空时,执行以下操作:
    a. 弹出栈顶元素。
    b. 如果弹出的元素大于maxValue,更新maxValue的值。
    c. 如果弹出的元素小于等于maxValue,判断其与下一个待比较元素的大小关系:
    i. 如果弹出的元素小于下一个待比较元素,将下一个待比较元素入栈。
    ii. 否则,跳过下一个待比较元素。
  4. 当所有元素都已比较完毕后,maxValue即为区间的最值。

C++代码实现

// 单调栈算法
#include<bits/stdc++.h>
#define reg register
using namespace std;

// 读取输入,并返回一个整数
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1; // 如果字符是负号,设置标志位为负
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48); // 将字符转换为数字并加到结果中
		ch=getchar();
	}
	return x*f; // 返回结果
}

// 输出结果,将整数转换为字符串并打印出来
inline void write(int x){
	if(x<0){
		putchar('-');
		x=-x; // 如果是负数,先打印负号再取反
	}
	if(x>9) write(x/10); // 如果数字大于9,递归调用函数处理十位数
	putchar(x%10+'0'); // 打印个位数
	return ;
}

const int MAXN=3000006; // 常量定义最大值
int n,ans[MAXN]; // 定义变量n和结果数组ans
vector<int > a; // 定义向量a存储输入数据
stack<int > s; // 定义栈s用于单调性判断

int main(){
	n=read(); // 从输入中读取数据的数量n
	a.push_back(0); // 在向量a的末尾添加一个元素0作为哨兵
	for(reg int i=1;i<=n;i++) a.push_back(read()); // 从输入中读取n个数据,并添加到向量a中
	for(reg int i=n;i>=1;i--){ // 从后向前遍历向量a中的元素
		while(!s.empty()&&a[s.top()]<=a[i]) s.pop(); // 如果栈不为空且栈顶元素小于等于当前元素,则弹出栈顶元素直到满足条件
		ans[i]=s.empty()?0:s.top(); // 如果栈为空,则结果为0,否则结果为栈顶元素,并将其压入栈中
		s.push(i); // 将当前元素压入栈中
	}
	for(reg int i=1;i<=n;i++){ // 从后向前遍历向量a中的元素,并打印结果
		write(ans[i]); // 将结果转换为字符串并打印出来
		putchar(' '); // 在每个结果后面添加一个空格以便区分不同的结果
	}
	return 0; // 程序正常结束,返回0
}

例题及题解

题目:给定一个整数数组nums和一个整数目标值target,请找出数组中和为目标值的那两个整数,并返回它们的数组下标。如果不存在这样的两个整数,则返回[-1,-1]。你可以假设每个输入只对应一次答案。你可以按任意顺序返回答案。

示例:nums = [2,7,11,15], target = 9。因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0,1]。解答过程如下:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值