数据结构与算法面试题查找最小的k个数
Posted zhiyong_will
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法面试题查找最小的k个数相关的知识,希望对你有一定的参考价值。
题目来源“数据结构与算法面试题80道”。
问题分析:这是一道比较经典的题目,查找最小的k个元素,最简单的方法就是对这n个整数排序,排序完成后,直接输出前k个最小的元素。那么最快的排序方法是快速排序,其算法的时间复杂度为O(nlogn)。是否还存在比这个更快的方法呢?
方法一:利用快速排序的思想,时间复杂度为O(n)
按照某个点将数组划分成左右两部分,左边的数都小于该划分节点,右边的数都大于该划分节点。如果最终该划分节点的位置小于k-1,则在右边节点中继续划分;如果最终该划分节点的位置大于k-1,则在左边节点中继续划分。这个过程直到最终的划分节点的位置正好为k-1。
int swap(int *a, int start, int end, int point_index){
int par_point = a[point_index];
while (start < end){
if (a[start] >= par_point && a[end] <= par_point){
int tmp = a[start];
a[start] = a[end];
a[end] = tmp;
start ++;
end --;
}else if(a[start] < par_point){
start ++;
}else{
end --;
}
}
return start;
}
void get_min_k(int *a, int length, int k){
if (k > length || NULL == a || length <= 0) return;
int new_index = swap(a, 0, length-1, k);
while (true){
if (new_index == k) break;
else if (new_index > k){
new_index = swap(a, 0, new_index, k);
}else{
new_index = swap(a, new_index, length-1, k);
}
}
}
方法二:利用堆排序,时间复杂度为O(nlogk)
上述方法的缺点是其对数组进行了修改,在堆排序中,可采用小顶堆,其中堆的大小为k,若此时堆的大小小于k时,则将数插入堆中;若此时堆中的大小大于等于k,则比较堆中最大的整数与待插入整数的大小,插入较小的整数。
void get_min_k(int *a, int length, int k, set<int> &s){
if (k > length || NULL == a || length <= 0) return;
for (int i = 0; i < length; i++){
if (s.size() < k){
s.insert(a[i]);
}else{
set<int>::iterator it = --s.end();
if (a[i] < *it){
s.erase(*it);
s.insert(a[i]);
}
}
}
}
以上是关于数据结构与算法面试题查找最小的k个数的主要内容,如果未能解决你的问题,请参考以下文章
堆的相关习题 面试题17.14最小的K个数 347前K个高频元素 373查找和最小的K对数字