剑指offer:最小的k个数
2014-04-17 14:53
232 查看
题目:输入n个整数,找出其中最小的k个数。
方法1:上面一篇博客我们利用快速排序的partition函数来将数组分成两部分,partition函数的返回值就是排序好的数组的最终下标,其左边是比它小的数,右边是比它大的数,这样我们只需要将partition的返回值与k做比较,如果与k相等,则返回;如果比k大,则最小的k个数在左边,则继续返回递归;如果比k小,则最小的k个数中有一部分在右边,则返回这部分到右边寻找。
优点:时间复杂度为O(n),效率还是挺不错的。
缺点:我们找到的最小的K个数已经打乱了顺序了,就是不是原来输入的顺序,显然这不是一种好的方法,还有有缺陷的。
void GetLeastNumbers_Solution1(int* input, int n, int* output, int k)
{
if(input == NULL || output == NULL || k > n || n <= 0 || k <= 0)
return;
int start = 0;
int end = n - 1;
int index = Partition(input, n, start, end);
while(index != k - 1)
{
if(index > k - 1)
{
end = index - 1;
index = Partition(input, n, start, end);
}
else
{
start = index + 1;
index = Partition(input, n, start, end);
}
}
for(int i = 0; i < k; ++i)
output[i] = input[i];
}
方法2:我们可以先创建一个大小为K的数据容器来存储最小的K个数,接下来我们每次从输入的n个整数中读入一个数,如果容器中已有的数字少于K,则直接把这次读入的整数放入容器中;如果容器中已有K个数,就是容器满了,此时我们不能插入新的数字而只能替换已有的数字了。找出这K个数的最大值,然后拿这次待插入的整数和最大值相比较。如果待插入的值比当前已有的最大值小,则用这个数替换当前已有的最大值;如果待插入的值比当前已有的最大值还大,那么这个数不可能是最小的K个整数之一,于是我们可以抛弃这个数。
我们可以用红黑树来实现这个数据容器,或者使用最大堆来实现。
第2种情况非常适合海量数据的处理,当n>>k的时候非常适合。
时间复杂度为:O(n*lgk)
方法1:上面一篇博客我们利用快速排序的partition函数来将数组分成两部分,partition函数的返回值就是排序好的数组的最终下标,其左边是比它小的数,右边是比它大的数,这样我们只需要将partition的返回值与k做比较,如果与k相等,则返回;如果比k大,则最小的k个数在左边,则继续返回递归;如果比k小,则最小的k个数中有一部分在右边,则返回这部分到右边寻找。
优点:时间复杂度为O(n),效率还是挺不错的。
缺点:我们找到的最小的K个数已经打乱了顺序了,就是不是原来输入的顺序,显然这不是一种好的方法,还有有缺陷的。
void GetLeastNumbers_Solution1(int* input, int n, int* output, int k)
{
if(input == NULL || output == NULL || k > n || n <= 0 || k <= 0)
return;
int start = 0;
int end = n - 1;
int index = Partition(input, n, start, end);
while(index != k - 1)
{
if(index > k - 1)
{
end = index - 1;
index = Partition(input, n, start, end);
}
else
{
start = index + 1;
index = Partition(input, n, start, end);
}
}
for(int i = 0; i < k; ++i)
output[i] = input[i];
}
方法2:我们可以先创建一个大小为K的数据容器来存储最小的K个数,接下来我们每次从输入的n个整数中读入一个数,如果容器中已有的数字少于K,则直接把这次读入的整数放入容器中;如果容器中已有K个数,就是容器满了,此时我们不能插入新的数字而只能替换已有的数字了。找出这K个数的最大值,然后拿这次待插入的整数和最大值相比较。如果待插入的值比当前已有的最大值小,则用这个数替换当前已有的最大值;如果待插入的值比当前已有的最大值还大,那么这个数不可能是最小的K个整数之一,于是我们可以抛弃这个数。
我们可以用红黑树来实现这个数据容器,或者使用最大堆来实现。
第2种情况非常适合海量数据的处理,当n>>k的时候非常适合。
时间复杂度为:O(n*lgk)
typedef multiset<int, greater<int> > intSet; typedef multiset<int, greater<int> >::iterator setIterator; void GetLeastNumbers_Solution2(const vector<int>& data, intSet& leastNumbers, int k) { leastNumbers.clear(); if(k < 1 || data.size() < k) return; vector<int>::const_iterator iter = data.begin(); for(; iter != data.end(); ++ iter) { if((leastNumbers.size()) < k) leastNumbers.insert(*iter); else { setIterator iterGreatest = leastNumbers.begin(); if(*iter < *(leastNumbers.begin())) { leastNumbers.erase(iterGreatest); leastNumbers.insert(*iter); } } } }
相关文章推荐
- 【剑指offer系列】 旋转元素的最小数字___8
- 剑指Offer面试题:7.旋转数组的最小数字
- 剑指offer(二十三)之最小的K个数
- 《剑指offer》java实现 输入n个数,找到其中最小的K个数
- 剑指offer-最小的k个数
- 《剑指offer》:[30]最小的K个数问题
- 剑指offer--快速排序递归实现,年龄排序O(N)实现,旋转数组最小值查找
- 剑指Offer(45)把数组排成最小的数
- 剑指offer—第二章算法之二分查找(旋转数组的最小值)
- 剑指offer 面试题30 最小的K个数
- 剑指Offer(11)旋转数组的最小元素
- 剑指offer:把数组排成最小的数
- 剑指offer 29 最小的k个数
- 剑指offer系列之31:把数组排成最小的数
- 剑指offer第6题 ,旋转数组的最小值。
- 剑指offer(二十五)之把数组排成最小的数
- 《剑指offer》:[11]旋转数组的最小数字
- 《剑指offer》:[33]把数组排成最小的数
- 《剑指offer》面试题8旋转数组的最小值
- 剑指offer第二十九题【最小的K个数】c++实现