0
点赞
收藏
分享

微信扫一扫

新手入门刷题(专题二)排序———>持续更新

清冷的蓝天天 2022-04-07 阅读 34

某csdn大佬推荐的新手刷题网站,快速入门!洛谷

新手入门刷题(专题二)排序———>持续更新


4.5

【深基9.例1】选举学生会

题目描述

学校正在选举学生会成员,有 n ( n ≤ 999 ) 名候选人,每名候选人编号分别从 1 到 n,现在收集到了 m (m ≤ 2000000 ) 张选票,每张选票都写了一个候选人编号。现在想把这些堆积如山的选票按照投票数字从小到大排序。

输入格式

输入 n和 m以及 m个选票上的数字。

输出格式

求出排序后的选票编号。

输入样例

5 10
2 5 2 2 5 2 2 2 1 2

输出样例

1 2 2 2 2 2 2 2 5 5

思路

上去就无脑冒泡,结果TLE感动了,本题正确思路是采用计数排序

代码

#include<iostream>
using namespace std;
int a[2000];
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int t;
        cin>>t;
        a[t]++;
    }
    int flag=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<a[i];j++){
            if(flag++) cout<<' ';
            cout<<i;
        }
    }
    return 0;
}

【模板】快速排序

题目描述

思路

每次迭代确保k值左边 <= k ,k 值右边 >= k, 即,每轮下来,确定一个k值的位置,快排模板是一定要记住的!!

这里简单记录一下位运算,>> 代表 右移

比如 6 的二进制为 0110,将其右移一位,变成 0011,即 3,因此 >>1 可以理解为 /2

代码

#include<iostream>
using namespace std;
int a[100010];
void quick_sort(int q[], int l, int r)
{
    //如果数组<=一个数,无需排序
    if (l >= r) return;
    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j)
    {
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    quick_sort(q, l, j);
    quick_sort(q, j + 1, r);
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
    }
    quick_sort(a,0,n-1);
    for(int i=0;i<n;i++){
        if(i<n-1){
            printf("%d ",a[i]);
        }else{
            printf("%d",a[i]);
        }
    }
    return 0;
}

【深基9.例4】求第 k 小的数

题目描述

思路

无论是求第k小数还是第k大数,都是快排的延伸,我们知道快排一轮可以确定一个数的位置,进行迭代的过程,我们只需要知道第k小数在该数字的左边还是右边,然后迭代单边即可,记住快排模板,加以改进即可。

代码

#include <iostream>
using namespace std;
const int N = 5000010;
int q[N];
//该模板是从第1个数开始的
int quick_sort(int q[], int l, int r, int k)
{
    if (l >= r) return q[l];
    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j){
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    if (j - l + 1 >= k) return quick_sort(q, l, j, k);
    else return quick_sort(q, j + 1, r, k - (j - l + 1));
}

int main(){
    int n, k;
    scanf("%d%d", &n, &k);
    //题目要求从第0个数开始,因此k++
    k++;
    //如果求第k大数,只需赋值k为如下代码即可
    //k = n-k+1;
    for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);
    cout << quick_sort(q, 0, n - 1, k) << endl;
    return 0;
}

[NOIP2006 普及组] 明明的随机数

题目描述

明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了 N 个 1 到 1000 之间的随机整数 ( N ≤ 100 ),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。

思路

本题分为两步,第一步去重复,第二步排序,去重在输入过程中,遍历数组判断该数字是否存在即可

代码

#include <iostream>
using namespace std;
const int N = 110;
int q[N];
//排序直接用快排模板
int quick_sort(int q[], int l, int r)
{
    if (l >= r) return q[l];
    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j){
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    quick_sort(q, l, j);
    quick_sort(q, j + 1, r);
}
int main(){
    int n;
    int len=1;
    scanf("%d", &n);
    for (int i = 0; i < n; i ++ ){
        int t;
        scanf("%d", &t);
        for(int j=0;j<len;j++){
            //如果输入的数字在数组中已存在,跳出本次循环
            if(q[j]==t) break;
            //否则在数组尾部插入该数字,并调整数组长度+1,确保数组尾部总有一个值为0的数字等待插入
            else if(q[j]==0){
                q[j]=t;
                len++;
                break;
            }
        }
    } 
    quick_sort(q, 0, len-2);
    //数组实际长度为len-1,在数字插入操作时,为了确保数组尾部总有一个值为0的数字,数组长度故意+1
    printf("%d\n", len-1);
    for (int i = 0; i < len-1; i ++ ){
        if(i<len-2) printf("%d ", q[i]);
        else printf("%d", q[i]);
    } 
    return 0;
}
举报

相关推荐

0 条评论