第二章上机实践报告

题目:找第k小的数
问题描述:设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数   (提示:函数int partition(int a[],int left,int right)的功能是根据a[left]~a[right]中的某个元素x(如a[left])对a[left]~a[right]进行划分,划分后的x所在位置的左段全小于等于x,右段全大于等于x,同时利用x所在的位置还可以计算出x是这批数据按升非降序排列的第几个数。因此可以编制int find(int a[],int left,int right,int k)函数,通过调用partition函数获得划分点,判断划分点是否第k小,若不是,递归调用find函数继续在左段或右段查找。)

输入格式:

输入有两行:

第一行是n和k,0<k<=n<=10000

第二行是n个整数

输出格式:

输出第k小的数

输入样例:

在这里给出一组输入。例如:

10 4
2 8 9 0 1 3 6 7 8 2
 

输出样例:

在这里给出相应的输出。例如:

2

代码

#include <iostream>
using namespace std;
int partition(int a[],int left,int right)
{//快速排序
 int x = a[left];
 while(left<right){
  while(left<right&&a[right]>=x) right--;
  a[left]=a[right];
        while(left<right&&a[left]<=x) left++;
     a[right]=a[left];
 }
 a[left]=x;
 return left; 
}
int find(int a[],int left,int right,int k)
{//找划分点,判断大小
 int pos =partition(a,left,right);
 if(k-1==pos)
    cout<<a[k-1]<<endl;
    else if(k-1<pos)
        find(a,left,pos-1,k);
    else
        find(a,pos+1,right,k);
    return 0;
}
int main()
{
 int n,k;
 cin>>n>>k;
 int a[1000];
 for(int i=1;i<=n;i++)
 {
  cin>>a[i];
 }
    int b;
 b=find(a,0,n-1,k);
 return 0;

时间复杂度:运用了分治法和快速排序法。用数组中的元素x对数组进行划分,分成左右两个区域,判断x是否为第k小的数,若是,则输出,若不是继续划分查找,平均时间复杂度则为O(n)

空间复杂度:find函数运用了递归,空间复杂度为O(logn)
心得体会:可能因为题目有提示,这道题目我写的挺顺畅的,我根据提示内容分别写出快排的算法和比较划分点大小的算法,理清楚寻找划分点大小算法的思路,在devC++中我能准确的运行结果,可是在pta中总是显示答案错误,我反复核查最终也没有找出哪里不对,以至于下课了也没能结对完成这道题目。回到宿舍后我又看了一遍题目和自己打的,发现自己打的思路都是正确的,然后最终通过看网上其他人写的代码例子才发现原来自己的数组范围没有按要求定好,导致了结果显示错误。总结:编程需要有耐心,静下心来理清思路,打代码过程中要注重细节,按要求书写规范。

posted on 2020-10-06 16:57  本杰迷  阅读(101)  评论(0编辑  收藏  举报