PAT (Basic Level) 1045 快速排序(思维)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_45458915/article/details/102711132

题目链接:点击查看

题目大意:根据快速排序的定义,找出主元,主元就是在未排序之前,当前位置之前的数都比其自身小,当前位置之后的数都比其自身大

题目分析:这个题可以暴力混分。。但没必要,n*n的时间复杂度就已经1e10了,肯定不是最优解,因为涉及到了最大值和最小值,我们可以用线性dp求一下截止到每个位置的最大值和最小值,正这跑一遍最大值,倒着跑一遍最小值,最后再正这跑一遍就出答案了,正这跑的时候只要满足条件的数,就可以记录下来了,条件就是当前的数小于等于记录的最小值,大于等于记录的最大值即可

网上说还有一种做法,我有考虑到,但没考虑的那么全面就没敢尝试,而且时间复杂度比这个要大,这个的时间复杂度是3*n,而那个的做法是说,主元都是在当前序列排序后位置不变的元素,所以我们可以开个辅助数组排个序,并且可以正这跑一遍最大值,边跑边判断就能出答案了,即当前的值比之前的最大值都要大,并且当前的值在排序后位置不变,不过这样一来有了排序,时间复杂度就到了nlogn了,而且这个原理不明。。有点玄学,还是正反跑一遍线性dp比较好理解

注意最后需要特别判断一下主元数为0的情况

代码:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream> 
#include<unordered_map>
using namespace std;

typedef long long LL;

const int inf=0x3f3f3f3f;

const int N=1e5+100;

struct Node
{
	int mmax,mmin;
}dp[N];

int a[N];

int main()
{
//  freopen("input.txt","r",stdin);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",a+i);
	dp[0].mmax=-inf;
	dp[n+1].mmin=inf;
	for(int i=1;i<=n;i++)
		dp[i].mmax=max(a[i],dp[i-1].mmax);
	for(int i=n;i>=1;i--)
		dp[i].mmin=min(a[i],dp[i+1].mmin);
	vector<int>ans;
	for(int i=1;i<=n;i++)
		if(dp[i].mmax<=a[i]&&dp[i].mmin>=a[i])
			ans.push_back(a[i]);
	cout<<ans.size()<<endl;
	if(ans.size())
	{
		cout<<ans[0];
		for(int i=1;i<ans.size();i++)
			cout<<' '<<ans[i];
	}
	cout<<endl;
	
	
	
	
	
	
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/102711132
今日推荐