PAT Basic 1045. 快速排序(25)

本文介绍了一种算法,用于确定快速排序过程中可能作为主元的元素数量,并给出了具体的实现代码。通过对输入序列的分析,该算法能找出满足条件的主元并按顺序输出。

问题描述:
著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的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

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;

const int maxn = 100005;
typedef long long LL;

LL a[maxn];
LL b[maxn], c[maxn];

int main()
{
    int n;
    cin >> n;
    for(int i = 0; i < n; i ++) {
        cin >> a[i];
        b[i] = a[i];
    }
    sort(b, b + n);
    int max = 0, k = 0;
    for(int i = 0; i < n; i ++) {
        if(a[i] > max)
            max = a[i];
        if(a[i] == max && a[i] == b[i])
            c[k ++] = b[i];
    }
    cout << k << endl;
    for(int i = 0; i < k; i ++) {
        if(i == 0)
            cout << c[i];
        else
            cout << " " << c[i];
    }
    cout << endl;
    return 0;
}
PAT 1045快速排序题目要求是给定划分后的 N 个互不相同的正整数的排列,找出有多少个元素可能是划分前选取的主元。若一个元素左边的元素都比它小,右边的元素都比它大,那么该元素可能是主元[^1][^2]。 ### 解题思路 - **普通方法**:对每个元素,检查其左边元素是否都比它小,右边元素是否都比它大。若都满足,则该元素可能是主元。 - **优化方法**:将原数组排序得到新数组,遍历原数组,若原数组元素与排序后对应位置元素相同,且该元素大于之前遍历过的最大元素,则它可能是主元。 ### 代码示例 #### 普通方法(部分运行超时) ```cpp #include <cstdio> using namespace std; const int maxn = 100001; int main() { int n; scanf("%d",&n); int a[maxn],s[maxn]; for(int i = 0; i < n; i++){ scanf("%d",&a[i]); } int sum = 0; for(int i = 0; i < n; i++){ int flag1 = 0,flag2 = 0; for(int j = i - 1; j >= 0; j--){ if(a[j] > a[i]){ flag1 = 1; break; } } if(!flag1){ for(int k = i + 1; k < n; k++){ if(a[k] < a[i]){ flag2 = 1; break; } } } if(flag1||flag2){ continue; } else{ s[sum++] = a[i]; } } printf("%d\n",sum); for(int i = 0; i < sum; i++){ printf("%d",s[i]); if(i != sum - 1){ printf(" "); } } printf("\n"); return 0; } ``` #### 优化方法 ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; int main(){ int n, k = 0, max = 0, save[100005]; cin >> n; vector<int> a(n), b(n); for (int i = 0; i < n; i++){ cin >> a[i]; b[i] = a[i]; } sort(a.begin(), a.end()); for (int i = 0; i < n; i++) { if (a[i] == b[i] && b[i] > max) save[k++] = b[i]; if (b[i] > max) max = b[i]; } cout << k << endl; if (k == 0) cout << endl; for (int i = 0; i < k; i++) { if (i == k - 1) {cout << save[i]; break;} cout << save[i] << " "; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值