B1045 快速排序(两种方法)类似B1040

题目

在这里插入图片描述

思路

快速排序的应用,不需要写一遍快排的代码。
坑点是测试点2,行末需要在输出一个换行。

两种思路:

  1. 参考柳神的,给出划分后的数列,由快排主元的定义,比前面的数都大,比后面的数都小,则相当于主元本身已经排好序了,那么利用快排将原数组排好序,对应位置相同的有可能是主元。再进行一次最大值的验证,当其左侧的数均小于它时,可以确定为主元。
    AC代码:
#include<bits/stdc++.h>
using namespace std;

int main(){
	int n; cin>>n;
	int a[n],b[n];
	for(int i=0;i<n;i++){
		cin>>a[i];
		b[i]=a[i];
	}
	sort(a,a+n);
	int max=0,step=0;
	int c[100000];
	for(int i=0;i<n;i++){
		if(a[i]==b[i] && b[i]>max){
			c[step++]=b[i];
		}
		if(b[i]>max) max=b[i];
	}
	
	cout<<step<<endl;
	for(int i=0;i<step;i++){
		cout<<c[i];
		if(i!=step-1) cout<<' '; 
	}
	cout<<endl;
} 

  1. 第二张思路类似于B1040(算是另一类25分题喜欢的考法?),正向遍历数组,统计每一位左侧的最大值;反向遍历数组,统计每一位右侧的最小值,并记录在数组中。
    两次遍历后,对每个a[i],都有对应leftMax[i]记录其左侧最大值,rightMin[i]记录其右侧最小值 。
    再建立新数组储存主元,排序后输出。
    AC代码:
#include<bits/stdc++.h>
using namespace std;

int main(){
	int n; cin>>n;
	int a[100001],lmax[100001],rmin[100001];
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
    lmax[0] = 0;                     //从a[0]开始判断,此时a[0]左侧最大值为0 
    for(int i = 1; i < n; i++){         // 开始向右侧遍历 
        if(a[i-1] > lmax[i-1]){      //若左侧值a[i-1]大于左侧最大值,则对该a[i],其对应的左侧最大值为a[i-1] 
            lmax[i] = a[i-1];
        }else{ 
            lmax[i] = lmax[i-1];  //反之则仍为前一位的左侧最大值 
        }
    } 
    
   rmin[n-1] = 1000000000;               //从末地址开始找右侧最小值,对末位,无右侧最小值,故定义一个极大值作为其右侧最小值 
    for(int i = n-2; i >= 0; i--){     //从倒数第二位向左侧遍历, 
        if(a[i+1] < rmin[i+1]){    //若前一位的值比其右侧最小值小 ,则更新其右侧最小值 
            rmin[i] = a[i+1];
        }else{ 
            rmin[i] = rmin[i+1];    //反之,其右侧最小值仍为后一位的右侧最小值 
        }
    } 
	int ans[100001];
	int num=0;
    //两次遍历后,对每个a[i],都有对应leftMax[i]记录其左侧最大值,rightMin[i]记录其右侧最小值 
    //找可能是主元的数
    for(int i = 0; i < n; i++){
        if(a[i] > lmax[i] && a[i] < rmin[i]){ //如果a[i]比它左边最大的数都大,比它右边最小的数都小 
            ans[num++] = a[i];  //则a[i]可能是主元,放入ans数组 
        } 
    } 

	cout<<num<<endl;
	sort(ans,ans+num);
	for(int i=0;i<num;i++){
		cout<<ans[i];
		if(i!=num-1) cout<<' '; 
	}
	cout<<endl;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值