这是一个经典的算法题,下面给出的算法都在给定的数组基础上进行,好处时不用分配新的空间,坏处是会破坏原有的数组,可以自己分配新的空间以避免对原有数组的破坏。

思路一

先直接排序,再取排序后数据的前k个数。

排序算法用最快的堆排序,复杂度也会达到O(N*logN).

void filterDown(int* disorder, int pos, int size){
int temppos=pos,temp=;
while(temppos<size/){
if(*temppos+<size){
if(disorder[*temppos+]>disorder[*temppos+]){
if(disorder[temppos]<disorder[*temppos+]){
temp=disorder[temppos];
disorder[temppos]=disorder[*temppos+];
disorder[*temppos+]=temp;
temppos=*temppos+;
}
else{
break;
}
}
else{
if(disorder[temppos]<disorder[*temppos+]){
temp=disorder[temppos];
disorder[temppos]=disorder[*temppos+];
disorder[*temppos+]=temp;
temppos=*temppos+;
}
else{
break;
}
}
}
else if(disorder[temppos]<disorder[*temppos+]){
temp=disorder[temppos];
disorder[temppos]=disorder[*temppos+];
disorder[*temppos+]=temp;
temppos=*temppos+;
}
else{
break;
} }
}
void heapSort(int* disorder, int size){
int bottomRowSize=;
while(bottomRowSize<size){
bottomRowSize*=;
}
int temp=,i=;
for(int j=size/-;j>=;j--){
filterDown(disorder, j, size);
}
for(int j=size-;j>;j--){
temp=disorder[];
disorder[]=disorder[j];
disorder[j]=temp;
filterDown(disorder,,j);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
const int size=;
const int maxnum = ;
const int k=;
int* disorder=new int[size];
srand((unsigned) time(NULL));
for(int i=;i<size;i++){
disorder[i]=rand()%maxnum;
}
heapSort(disorder,size);
for(int i=;i<k;i++){
cout<<disorder[i]<<endl;
}
return ;
}

当k接近于N时,可以用这种算法。

思路二

先排序前k个数,对于后面N-k个数,依次进行插入。

时间复杂度为O(k*n)

void insertSort(int* disorder, int size){
int temp=,i=;
for(int j=;j<size;j++){
temp=disorder[j];
for(i=j;i>;i--){
if(temp<disorder[i-]){
disorder[i] = disorder[i-];
}
else{
break;
}
}
disorder[i]=temp;
}
} int _tmain(int argc, _TCHAR* argv[])
{
const int size=;
const int maxnum = ;
const int k=;
int* disorder=new int[size];
srand((unsigned) time(NULL));
int i=,temp;
for(;i<size;i++){
disorder[i]=rand()%maxnum;
}
insertSort(disorder,k);
for(int j=k;j<size;j++){
temp=disorder[j];
for(i=k-;i>=;i--){
if(temp<disorder[i]){
disorder[i+] = disorder[i];
}
else{
break;
}
}
disorder[i+]=temp;
} for(int i=;i<k;i++){
cout<<disorder[i]<<endl;
}
return ;
}

当k很小时,可以用这种算法

思路三

对前k个数,建立最大堆,对于后面N-k个数,依次和最大堆的最大数比较,如果小于最大数,则替换最大数,并重新建立最大堆。

时间复杂度为O(N*logk)

void filterDown(int* disorder, int pos, int size){
int temppos=pos,temp=;
while(temppos<size/){
if(*temppos+<size){
if(disorder[*temppos+]>disorder[*temppos+]){
if(disorder[temppos]<disorder[*temppos+]){
temp=disorder[temppos];
disorder[temppos]=disorder[*temppos+];
disorder[*temppos+]=temp;
temppos=*temppos+;
}
else{
break;
}
}
else{
if(disorder[temppos]<disorder[*temppos+]){
temp=disorder[temppos];
disorder[temppos]=disorder[*temppos+];
disorder[*temppos+]=temp;
temppos=*temppos+;
}
else{
break;
}
}
}
else if(disorder[temppos]<disorder[*temppos+]){
temp=disorder[temppos];
disorder[temppos]=disorder[*temppos+];
disorder[*temppos+]=temp;
temppos=*temppos+;
}
else{
break;
} }
} int _tmain(int argc, _TCHAR* argv[])
{
const int size=;
const int maxnum = ;
const int k=;
int* disorder=new int[size];
srand((unsigned) time(NULL));
int i=,temp;
for(;i<size;i++){
disorder[i]=rand()%maxnum;
}
for(int j=k/-;j>=;j--){
filterDown(disorder, j, k);
}
for(int j=k;j<size;j++){
if(disorder[j]<disorder[]){
disorder[]=disorder[j];
filterDown(disorder,,k);
}
}
for(int j=k-;j>;j--){
temp=disorder[];
disorder[]=disorder[j];
disorder[j]=temp;
filterDown(disorder,,j);
}
for(int i=;i<k;i++){
cout<<disorder[i]<<endl;
}
return ;
}

当k和N都很大时,这种算法比前两种算法要快很多。

找出N个数中最小的k个数问题(复杂度O(N*logk))的更多相关文章

  1. Java找N个数中最小的K个数,PriorityQueue和Arrays.sort()两种实现方法

    最近看到了 java.util.PriorityQueue.刚看到还没什么感觉,今天突然发现他可以用来找N个数中最小的K个数. 假设有如下 10 个整数. 5 2 0 1 4 8 6 9 7 3 怎么 ...

  2. 求一个数组中最小的K个数

    方法1:先对数组进行排序,然后遍历前K个数,此时时间复杂度为O(nlgn); 方法2:维护一个容量为K的最大堆(<算法导论>第6章),然后从第K+1个元素开始遍历,和堆中的最大元素比较,如 ...

  3. [算法]找到无序数组中最小的K个数

    题目: 给定一个无序的整型数组arr,找到其中最小的k个数. 方法一: 将数组排序,排序后的数组的前k个数就是最小的k个数. 时间复杂度:O(nlogn) 方法二: 时间复杂度:O(nlogk) 维护 ...

  4. LeetCode 5071. 找出所有行中最小公共元素(Java)

    题目:5071. 找出所有行中最小公共元素 给你一个矩阵 mat,其中每一行的元素都已经按 递增 顺序排好了.请你帮忙找出在所有这些行中 最小的公共元素. 如果矩阵中没有这样的公共元素,就请返回 -1 ...

  5. 求给定数据中最小的K个数

    public class MinHeap { /* * * Top K个问题,求给定数据中最小的K个数 * * 最小堆解决:堆顶元素为堆中最大元素 * * * */ private int MAX_D ...

  6. 【算法】数组与矩阵问题——找到无序数组中最小的k个数

    /** * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) * 过程: * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 * 在堆里的k个元素中堆顶的元素是最小的k个数 ...

  7. 《程序员代码面试指南》第八章 数组和矩阵问题 找到无序数组中最小的k 个数

    题目 找到无序数组中最小的k 个数 java代码 package com.lizhouwei.chapter8; /** * @Description: 找到无序数组中最小的k 个数 * @Autho ...

  8. 小米笔试题:无序数组中最小的k个数

    题目描述 链接:https://www.nowcoder.com/questionTerminal/ec2575fb877d41c9a33d9bab2694ba47?source=relative 来 ...

  9. Python3求m以内的素数、求m个数中最小的n个数

    [本文出自天外归云的博客园] 题1:求m以内的素数(m>2) def find_all_primes_in(m): def prime(num): for i in range(2, num): ...

随机推荐

  1. 重拾Object--(一)初识

    Java中的Object类有着特殊的意义,他是所有其它类的父类,查看Object类的源代码,可以发现代码不多,逻辑也很简单. Java所有类的源代码我们都可以在JDK的文件中查看,在JDK下会有一个名 ...

  2. promise 如何知道所有的回调都执行完了?

    var fs = require('fs'); /** * @return {object} Promise */ function doThing(fileName) { // ... // con ...

  3. 关于解决coursera视频缓冲问题

    关于解决coursera视频缓冲问题 之前使用coursera,不FQ的话,视频根本加载不出来,于是每次都FQ过去看的视频.后来发现可以直接修改hosts就可以了. 以下方法来源知乎的回答(侵删). ...

  4. C++之参数总结

    函数的形参为函数提供了已命名的局部存储空间,它是在函数的形参表中定义的,并由调用函数时传递给函数的实参初始化,而形参的 初始化与变量的初始化一样,如果形参具有非引用类型,则复制实参的值,如果形参为引用 ...

  5. FAN54015 充電電流 軟硬體設定

    Ex1: Vrsense 選 37.4 mV --- 在第二張圖 Rsense 選 50 mΩ --- 在第三張圖 37.4 / 50 = 748 mA Ex2: Vrsense 選 44.2 mV ...

  6. 关于c++的string的operator =

    在 c++ primer 5 中在说到string的章节里面有这样一句话: string s5 = "hiya"; // copy initialization 也就是说,这里说上 ...

  7. 【COGS2622】后缀平衡树

    这是个后缀平衡树的裸题.... 然后傻逼的我调了一下午. #include<bits/stdc++.h> typedef long long ll; using namespace std ...

  8. mybatis官网学习

    javaType:一个 Java 类的完全限定名,或一个类型别名(参考上面内建类型别名 的列表) .如果你映射到一个 JavaBean,MyBatis 通常可以断定类型. 然而,如果你映射到的是 Ha ...

  9. 排序算法总结(C语言版)

    排序算法总结(C语言版) 1.    插入排序 1.1     直接插入排序 1.2     Shell排序 2.    交换排序 2.1     冒泡排序 2.2     快速排序 3.    选择 ...

  10. tmpfs文件系统

    centos 7测试OK 创建挂载点,挂载 mkdir -p /run/testdirmount -nt tmpfs -o size=500m,mode=755 tmpfs /run/testdir