(PTA乙级)1045 快速排序 (单调栈思想)

著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的 N 个互不相同的正整数的排列,请问有多少个元素可能是划分前选取的主元?

例如给定 N=5, 排列是1、3、2、4、5。则:

  • 1 的左边没有元素,右边的元素都比它大,所以它可能是主元;
  • 尽管 3 的左边元素都比它小,但其右边的 2 比它小,所以它不能是主元;
  • 尽管 2 的右边元素都比它大,但其左边的 3 比它大,所以它不能是主元;
  • 类似原因,4 和 5 都可能是主元。

因此,有 3 个元素可能是主元。

输入格式:

输入在第 1 行中给出一个正整数 N(≤105); 第 2 行是空格分隔的 N 个不同的正整数,每个数不超过 109。

输出格式:

在第 1 行中输出有可能是主元的元素个数;在第 2 行中按递增顺序输出这些元素,其间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

5
1 3 2 4 5

输出样例:

3
1 4 5
采用单调栈

本题的关键就是判断元素X的左边是否存在比X更大的元素,X的右边是否存在比X更小的元素。如果使用嵌套for循环的话可以暴力解决,时间复杂度为O(n2);当然,也可以使用数组max和数组min,分别存储元素X左边的最大值和X右边的最小值,采用动态规划思想解决。

这里我使用的是单调栈,其实也就是动态规划的思想,使用一个单调递增栈和一个单调递减栈。

注意,如果没有元素满足情况,在输出0之后还要再输出一个空行

#include<iostream>
#include<algorithm>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
using namespace std;
 
int main(){
	int n;
	cin>>n;
	long long *num=new long long[n+2];
	int *small=new int [n+2];
	int *big=new int[n+2];
	
	for(int i=0;i<n;i++){
		cin>>num[i];
		small[i]=-1;
		big[i]=-1;
	}
	
	stack<int> s1;
	// 向右单调递增栈 
	for(int i=0;i<n;i++){
		while(!s1.empty()&&num[i]<num[s1.top()]){
			small[s1.top()]=i;
			s1.pop();
		}
		s1.push(i);
	}
	stack<int> s2;
//	向左单调递减栈 
	for(int i=n-1;i>=0;i--){
		while(!s2.empty()&&num[i]>num[s2.top()]){
			big[s2.top()]=i;
			s2.pop();
		}
		s2.push(i);
	}
	 
	vector<long long> v1;
	for(int i=0;i<n;i++){
		if(small[i]<0&&big[i]<0) v1.push_back(num[i]);
	}
	cout<<v1.size()<<endl;
	if(v1.size()>0){
		sort(v1.begin(),v1.end(),[&](long long a,long long b){
		return a<b;
		});
		cout<<v1[0];
		for(int i=1;i<v1.size();i++)
		cout<<" "<<v1[i];
	}
	// 如果没有元素了,直接输出一个空行 
	cout<<endl;
	return 0;
}

### PTA乙级考试准备资料与题目解析 #### 关于PTA乙级考试 PTA(Programming Teaching Assistant)是一个在线编程练习平台,主要用于帮助学生提高程序设计能力。其中,PAT Basic Level(即PTA乙级)主要面向初学者,考察基础算法和数据结构的知识[^1]。 #### 备考建议 备考PTA乙级考试时,可以按照以下几个方面进行准备: 1. **熟悉基本语法** 掌握C/C++或Python的基础语法是通过PTA乙级考试的关键之一。这包括但不限于变量定义、条件语句、循环控制以及函数调用等内容。 2. **理解常见算法** 对一些常见的简单算法有所了解是非常必要的,比如排序算法中的冒泡排序、选择排序等;字符串处理方面的基础知识也是不可忽视的部分。 3. **多做模拟试题** 刷题是最有效的学习方法之一。“刷完PTA上的(PAT (Basic Level) Practice (中文))”提到共有约一百一十个左右不同类型的习题可供练习。这些题目覆盖了大部分可能出现的考点,并且能够有效提升解题速度与准确性。 4. **注意细节问题** 在实际操作过程中可能会遇到各种各样的边界情况或者特殊输入形式,因此平时训练的时候就要养成良好的习惯去考虑全面的情况[^2]。 #### 示例代码展示 下面给出一段用于验证某个整数是否为完全平方数的小例子作为参考: ```python import math def is_perfect_square(n): if n < 0: return False sqrt_n = int(math.sqrt((n+1)/2)) # 这里利用了一个技巧来减少计算量 return sqrt_n * sqrt_n == ((n+1)//2) print(is_perfect_square(8)) ``` 此段代码展示了如何快速判断给定数值加上一之后除以二所得结果是否为完美平方根的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值