实践题目
2-1 找第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
算法描述
题目提示得很明白,要对所给数组数组进行划分,因此需要写一个partition函数定义left和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函数继续在左段或右段查找。
具体代码如下:
#include<iostream> using namespace std; int partition(int a[], int left, int right) { int i = left, j = right + 1; int x = a[left]; while(left < right) { while(a[++i] < x && i < right); while(a[--j] > x); if(i >= j) break; swap(a[i], a[j]); } a[left] = a[j]; a[j] = x; return j; } int find(int a[], int left, int right, int k) { int t = partition(a, left, right); if(k - 1 == t) cout << a[k - 1]; else if(k - 1 < t) find(a, left, t, k); else find(a, t + 1,right, k); return 0; } int main() { int a[1000]; int n, k; cin >> n >> k; for(int i = 0; i < n; i++) { cin >> a[i]; } find(a, 0, n - 1, k); return 0; }
算法时间及空间复杂度分析(要有分析过程)
时间复杂度:
快速排序算法在数组中选择一个元素,将数组分为两部分,使得 第一部分中的所有元素都小于或等于该元素,而第二部分的所有元素都大于该元素。对第一部分递归地应用快速排序算法,然后对第二部分递归地应用快速排序算法。
最坏情况:划分的两个区域分别包含n-1个元素和1个元素,如果每一步都出现这种情况,其复杂性为 O(1) n≤1 T(n)= T(n-1)+O(n) n>1 解得:T(n)=O(n2)
最好情况:每次划分所取的基准都恰好为中值,即每次划分都产生两个大小为n/2的区域, O(1) n≤1 T(n)= 2T(n/2)+O(n) n>1 解得:T(n)=O(nlogn)
空间复杂度:
空间复杂度我还不会算,上网查了一下。
最优的情况下空间复杂度为:O(logn) ;每一次都平分数组的情况
最差的情况下空间复杂度为:O( n ) ;退化为冒泡排序的情况
https://blog.csdn.net/A_BlackMoon/article/details/81064712
心得体会(对本次实践收获及疑惑进行总结)
如果是老师课上讲了这个知识点然后让我们做的话,我可能这道题会特别难下手,甚至思绪千奇百怪,但是我又绝对这道题很好,几乎是全结合上了老师讲的内容,对我来说无疑是加深知识的好题,当时和同伴在上机时,时常卡到我们的点的就是段错误问题,不过到现在我都还是不知道怎么去避免段错误,只能不断地试,试着是不是因为这个原因错了,还是什么原因错了,上机两次,都是段错误的问题,第一次的段错误找了特别久才能找到,这道题的段错误试着找就被找到了,但我还是不知道段错误到底是怎么回事,上网查了也有好些原因,但有时套进题里就是不知道怎么改它了。