在O(n)时间内查找数组内第k小的数
2016-12-01 13:02
176 查看
前一阵子做作业,看到了这个,要求在 O(n) 时间内查找前 k 小的 k 个数, 给出的提示是,先在 O(n) 时间内查找到第 k 小的数.由此想到,此前一直用 的 sort 函数,排完序后找下标为 k-1 的那个数,却从来没有考虑过具体的 实现.结合前一阵子学习的快速排序算法,大致对此有了新的认识.
首先给出一个函数,可以求出轴值在(排完序的)数组中的位置.
这里是假设区间的第一个数为轴值.
int Partition(int Array[],int left,int right)//二分查找区间 { int i = left, j = right; int pivot = Array[left];//轴值 while(i != j) { while(Array[j]>pivot && i<j) j--; if(i < j) Array[i] = Array[j], i++; while(Array[i]<=pivot && i<j) i++; if(i < j) Array[j] = Array[i], j--; } Array[i] = pivot; return i;//返回轴值的位置 }
下面再进行二分查找,查找第 k 小的数.
int Find(int Array[],int left,int right,int k) { if(left == right) return Array[left]; int pivot = Partition(Array,left,right);//轴值的位置 int num = pivot - left + 1; if(num == k) return Array[pivot]; else if(num < k) return Find(Array,pivot+1,right,k-num); else return Find(Array,left,pivot-1,k); }
这里,Find函数的返回值就是第k小的数val。
接下来,将这个数val作为轴值,调用Partition函数,即可得到分成两
块的区间,左边区间的数全部不大于val。左边的区间里的数即为所
求。整个算法的时间复杂度为O(n).
相关文章推荐
- 面试算法:lg(k)时间查找两个排序数组合并后第k小的元素
- 查找数组最大值最小值:时间复杂度最多为:o(3n/2)
- 题目:输入一个已经按升序排序过的数组和一个数字, 在数组中查找两个数,使得它们的和正好是输入的那个数字。 要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。 例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,
- 输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字 时间复杂度O(NlogN) 空间复杂度O(1)
- 查找数组中第K大的值
- 算法设计--查找无序数组中第K大的数字
- 线性时间内查找第K小(大)算法
- 线性时间复杂度求数组中第K大数
- 在旋转后的有序数组中查找元素,要求O(logn)的时间复杂度
- 查找两个已经排好序的数组的第k大的元素
- 给出一个数组,要求查找出这个数组中按顺序排第K大的数字
- 找包含N个元素的数组里第K大的元素(引申:快速排序、找中位数、找前K大的元素)的时间复杂度
- 查找两个已经排好序的数组的第k大的元素
- 算法导论标准版快速排序和线性时间求解数组第K小数
- 输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字 时间复杂度O(NlogN)
- 在旋转后的有序数组中查找元素,要求O(logn)的时间复杂度
- 两个有n个数的整数数组,都排好序了。 用O(n)的时间查找两个数组是否有相同的数字。
- 查找数组中第K大元素
- 算法设计--查找无序数组中第K大的数字
- 线性时间查找第k大元素