1. 实践题目名称:找第k小的数
2. 问题描述:输入k和一个数组,输出数组中第k小的数,且算法时间复杂度为O(n)
3. 算法描述:由 int Partition(int a[], int left, int right) 、int Find(int a[], int left, int right, int k) 、int main() 三部分组成
(1)int Partition(int a[], int left, int right)
Partition函数的功能是将输入的数组进行排序,使得排序后数组在我们所选取基准左边的数都小于基准,在所选取基准右边的数都大于基准
实现过程:int x = a[left] 将x设置为数组中的基准
while(a[++i]<x&&i<right) 从基准右边开始找比基准小的数,找到就用 i 进行标记
while(a[--j]>x) 从a[right]左边开始找比基准大的数,找到就用 j 进行标记
当 i < j 时,则那时被i 和 j 标记的数互相交换
当 i >= j 时 则数组已经划分完成,将基准x放在a[j]的位置上,跳出循环,返回此时的j的下标
(2)int Find(int a[], int left, int right, int k)
Find函数的功能是借助Partition函数返回的下标j来找出数组中第k小的数
实现过程:if(k-1==j) cout<<a[k-1] 如果要找的第k小的数(第k小的数在排序好的数组中的下标为k-1)下标k-1等于Partition函数返回的基准下标j,直接输出j
else if(k-1<j) Find(a,left,j-1,k) 如果要找的第k小的数的下标小于基准下标j,则在缩小范围(缩小至left到基准-1)的数组内递归Find函数找出第k小的数
else Find(a,j+1,right,k) 如果要找的第k小的数的下标大于基准下标j,则在缩小范围(缩小至基准+1到right)的数组内递归Find函数找础第k小的数
(3)int main() 进行元素的输入、存储、Find函数的调用、输出最后结果
4.算法时间及空间复杂度分析:运用分治法跟快速排序法,利用基准x将输入数组划分为左右两部分,再根据要找的数与基准x之间的大小关系来找出数组中第k小的数,平均时间复杂度为O(n)
5.心得体会:对函数递归跟如何运用分治法解决问题有了进一步的理解,比起直接在输入数组里面挨个比较数据大小然后输出第k小数的暴力算法,这种运用分治法将寻找第k小数这个问题分解为对输入数组进行快速排序然后再寻找题目所需的数的算法显然要更巧妙跟节省时间,已经通过一年的学习,我们不能仅仅局限于解决问题的层面,还要去寻找探寻更加简便快捷的方法来解决问题
浙公网安备 33010602011771号