排序经典题

问题描述

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

第 1 行为 1 个正整数,表示所生成的随机数的个数: NN

第 2 行有 NN 个用空格隔开的正整数,为所产生的随机数。
输出格式

2 行,第 1 行为 1 个正整数 MM,表示不相同的随机数的个数。

第2行为 MM 个用空格隔开的正整数,为从小到大排好序的不相同的随机数。
样例一
input

10
20 40 32 67 40 20 89 300 400 15

output

8
15 20 32 40 67 89 300 400

数据范围与约定

时间限制: 1s1s

内存限制: 256MB

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
unsigned a[110],b[1010];
int main()
{
    unsigned N;
    cin>>N;
    for(int i=1;i<=N;i++)
    {
        cin>>a[i];
        b[a[i]]++;
    }
    int flag=1,sum=0;
    for(int i=1;i<1005;i++)
    {
        if(b[i]) sum++;

    }

    cout<<sum<<endl;

    for(int i=1;i<1005;i++)
    {

        if(flag)
        {
            if(b[i])
            {
            cout<<i;    
            flag=0;
            i++;
            }   
        }
        if(b[i]) cout<<" "<<i;
    }
    return 0;
 } 

78题

问题描述

在一个旧式的火车站旁边有一座桥,其桥面可以绕河中心的桥墩水平旋转。一个车站的职工发现桥的长度最多能容纳两节车厢,如果将桥旋转 180 度,则可以把相邻两节车厢的位置交换,用这种方法可以重新排列车厢的顺序。于是他就负责用这座桥将进站的车厢按车厢号从小到大排列。他退休后,火车站决定将这一工作自动化,其中一项重要的工作是编一个程序,输入初始的车厢顺序,计算最少用多少步就能将车厢排序。
输入格式

2 行数据,第一行是车厢总数 NN(N≤10000N≤10000),第二行是 NN 个不同的数表示初始的车厢顺序。
输出格式

一个数据,即最少的旋转次数。
样例一
input

4
4 3 2 1

output

6

数据范围与约定

时间限制: 1s1s

内存限制: 256MB

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
unsigned a[10010];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    cin>>a[i];
    int sum=0;
    for(int i=1;i<n;i++)
    {
            for(int j=1;j<=n-i;j++)
        {
            if(a[j]>a[j+1])
            {
            swap(a[j],a[j+1]);
            sum++;
            }
        }       
    }
    cout<<sum;
    return 0;
}

79
众数

时间限制: 1 s 空间限制: 1000 KB 题目等级 : 青铜 Bronze 题目描述Description

由文件给出N个1到30000间无序数正整数,其中1≤N≤10000,同一个正整数可能会出现多次,出现次数最多的整数称为众数。求出它的众数及它出现的次数。
输入描述Input Description

输入文件第一行是正整数的个数N,第二行开始为N个正整数。
输出描述Output Description

输出文件有若干行,每行两个数,第1个是众数,第2个是众数出现的次数。
样例输入Sample Input

12

2 4 2 3 2 5 3 7 2 3 4 3
样例输出Sample Output

2 4

3 4
数据范围及提示Data Size & Hint

#include<iostream>
using namespace std;
int a[100001];
int tot=0;
int b[100001];
int ma;
int maxn;
int main()
{
   int n;
    cin>>n;
   for(int i=1;i<=n;i++)
   {
        cin>>a[i];        
         b[a[i]]++;
        if(b[a[i]]>maxn)        
         maxn=b[a[i]];
        if(a[i]>ma)        
         ma=a[i];     
    }

     for(int i=0;i<=ma;i++)
     {
         if(b[i]==maxn)
         {
             cout<<i<<" "<<b[i]<<endl;
         }
     }
     return 0;
 }

快速排序
c++一本通上的讲法

#include<iostream>
using namespace std;
int d[10]={3, 1, 4, 1, 5, 9, 2, 6, 7, 5};
int n=10;

void quickSort(int num[], int l, int r){
    if(l>=r)    return;
    int x=num[l], i=l, j=r;//l的值给了i r的值给了j
    //以x为基准分为两部分
    while(i<=j){
        while(num[i]<x) i++;
        while(num[j]>x) j--;
        if(i<=j){
            swap(num[i], num[j]);
            i++;
            j--;
        }
    }
    //递归、分治处理
    if(l<j) quickSort(num, l, j);
    if(i<r) quickSort(num, i, r);
}

int main(){
    quickSort(d, 0, n-1);
    for(int i=0; i<n; i++)
        cout<<d[i]<<" ";
    return 0;
}

快速排序经典代码

#include<iostream>
using namespace std;
int d[10]={3, 1, 4, 1, 5, 9, 2, 6, 7, 5};
int n=10;

void quickSort(int num[], int l, int r){
    if(l>=r)    return;
    int x=num[l], i=l, j=r;
    while(i!=j){
        //chai east, bu west
        while(j>i && num[j]>=x) j--;
        num[i]=num[j];
        //chai west, bu east
        while(i<j && num[i]<=x) i++;
        num[j]=num[i];
    }
    num[i]=x;
    quickSort(num, l, i-1);
    quickSort(num, i+1, r);
}

int main(){
    quickSort(d, 0, n-1);
    for(int i=0; i<n; i++)
        cout<<d[i]<<" ";
    return 0;
}

下面我们来具体分析下程序怎么运行的,

quickSort(d, 0, 5);代表以靠最有一个元素5作为基数,

程序初始化时候p=0,r=5,i=-1,j=0,key=5

quicksort

通过上图我们观察到:

1.i逐渐增加,它一直代表着小于key=5的最后一个元素,j也在主键增加,一直到key前面一个元素停止

2.此时循环到了最后一个元素7,以5为基数的循环已经结束,此时i=1,a[i+1]=6,交换6和5交换,完成本轮循环

返回i+1=2,依索引2为分界线拆分2个数组,进入递归循环,执行类似上图操作

第四、总结

快速排序之所以快,相比冒泡排序他的交换是跳跃式的,它的最差时间复杂度是O(N2) 和冒泡一样,但是它的平均时间复杂度是O(nlog2N),是一种就地排序算法,
快排图解

归并排序

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2路归并。
算法:
1把长度为n的输入序列分成两个长度为n/2的子序列;
2对这两个子序列分别采用归并排序;
3将两个排序好的子序列合并成一个最终的排序序列。
归并排序

参考代码
案例

#include<iostream>
#include<algorithm>
using namespace std;
int d[10]={3, 1, 4, 1, 5, 9, 2, 6, 7, 5};
int n=10;

void mergeSort(int num[], int l, int r){
    if(l>=r)    return;
    int mid=(l+r)/2;
    mergeSort(num, l, mid);
    mergeSort(num, mid+1, r);
    //merge
    int d[10000], x=l;
    int i=l, j=mid+1;
    while(i<=mid && j<=r){
        if(num[i]<num[j])
            d[x++]=num[i++];
        else
            d[x++]=num[j++];
    }
    while(i<=mid)
        d[x++]=num[i++];
    while(j<=r)
        d[x++]=num[j++];
    for(int k=l; k<=r; k++)
        num[k]=d[k];
}

int main(){
    mergeSort(d, 0, n-1);
    reverse(d, d+n);
    for(int i=0; i<n; i++)
        cout<<d[i]<<" ";
    return 0;
}

时间复杂度: O(nlogn)
最好情况: O(nlogn)
最坏情况: O(nlogn)
空间复杂度: O(n)
排序方式: Out-Place
稳定性: 稳定
这里写图片描述
这里写图片描述
这里写图片描述

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值