1045. 快速排序(25)-PAT乙级真题

快速排序主元分析
本文介绍了一种基于快速排序算法的主元分析方法。通过对已排序序列进行比对,找出可能作为主元的元素,即那些在排序前后位置不变且满足左右元素大小约束的元素。文章提供了完整的C++实现代码,并通过实例演示了如何确定哪些元素可以作为主元。

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

分析:对原序列sort排序,逐个比较,当当前元素没有变化并且它左边的所有值的最大值都比它小的时候就可以认为它一定是主元(很容易证明正确性的,毕竟无论如何当前这个数要满足左边都比他小右边都比他大,那它的排名【当前数在序列中处在第几个】一定不会变)~
如果硬编码就直接运行超时了…后来才想到这种方法~
一开始有一个测试点段错误,后来才想到因为输出时候v[0]是非法内存,改正后发现格式错误(好像可以说明那个第2个测试点是0个主元?…)然后加了最后一句printf("\n");才正确(难道是当没有主元的时候必须要输出空行吗…)

#include <iostream>
#include <algorithm>
#include <vector>
int v[100000];
using namespace std;
int main() {
    int n, max = 0, cnt = 0;
    scanf("%d", &n);
    vector<int> a(n), b(n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &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)
            v[cnt++] = b[i];
        if (b[i] > max)
            max = b[i];
    }
    printf("%d\n", cnt);
    for(int i = 0; i < cnt; i++) {
        if (i != 0) printf(" ");
        printf("%d", v[i]);
    }
    printf("\n");
    return 0;
}

### 关于PAT乙级考试题目及解析 #### 背景介绍 PAT(Programming Ability Test)乙级考试主要面向编程入门者设计,其难度适中,适合初学者巩固基础知识并提升实际编码能力。这类试题通常涉及基本的数据结构、算法逻辑以及程序设计技巧。 #### 题目特点 根据历年 PAT 乙级真题分析[^1],这些题目涵盖了数组操作、字符串处理、简单排序与查找等内容。对于数据结构初学者而言,它们是非常好的练手材料。通过尝试不同的解法来解决同一道题目,可以有效提高思维灵活性和代码实现能力。 #### 示例题目及其解答 以下是基于过往资料整理的一道典型 PAT 乙级题目: **题目描述** 给定一组试机座位号与对应的正式考试座位号之间的映射关系,请帮助迟到的考生找到自己的正式考试位置编号[^4]。 **输入格式** 第一行为两个正整数 N 和 M (N ≤ 10^5, M ≤ 10^4),分别表示总的考生人数和询问次数;随后一行包含 N 个互不相同的非负整数 Si 表示每位考生的试机座位号;再接着一行为 N 个同样长度的不同非负整数 Ai ,代表对应试机座次下的真实考场安排序号;最后连续给出 M 条查询记录 Qi 请求定位具体某人的最终分配情况。 **输出格式** 针对每次提问返回单独一行答案即目标人员的确切考室代号或者 "- " 如果该学员未参与此次评测活动的话。 ```python def find_exam_seat(n, m, try_seats, exam_seats, queries): seat_map = {try_seats[i]: exam_seats[i] for i in range(len(try_seats))} results = [] for query in queries: if query in seat_map: results.append(str(seat_map[query])) else: results.append("-") return "\n".join(results) if __name__ == "__main__": n, m = map(int, input().split()) try_seats = list(map(int, input().split())) exam_seats = list(map(int, input().split())) queries = [int(input()) for _ in range(m)] print(find_exam_seat(n, m, try_seats, exam_seats, queries)) ``` 上述代码片段展示了如何利用字典存储键值对从而快速检索所需信息的方法之一。 #### 总结反思 尽管部分复杂度较高的问题可能存在边界条件难以覆盖全面的情况[^2][^3],但总体来看,只要掌握了扎实的基础理论知识加上反复实践演练,就能从容应对大多数挑战。同时也要注意培养良好的时间管理习惯,在有限时间内完成高质量作答尤为重要。
评论 14
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值