找出N个数中最小的k个数问题(复杂度O(N*logk))
这是一个经典的算法题,下面给出的算法都在给定的数组基础上进行,好处时不用分配新的空间,坏处是会破坏原有的数组,可以自己分配新的空间以避免对原有数组的破坏。
思路一
先直接排序,再取排序后数据的前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))的更多相关文章
- Java找N个数中最小的K个数,PriorityQueue和Arrays.sort()两种实现方法
最近看到了 java.util.PriorityQueue.刚看到还没什么感觉,今天突然发现他可以用来找N个数中最小的K个数. 假设有如下 10 个整数. 5 2 0 1 4 8 6 9 7 3 怎么 ...
- 求一个数组中最小的K个数
方法1:先对数组进行排序,然后遍历前K个数,此时时间复杂度为O(nlgn); 方法2:维护一个容量为K的最大堆(<算法导论>第6章),然后从第K+1个元素开始遍历,和堆中的最大元素比较,如 ...
- [算法]找到无序数组中最小的K个数
题目: 给定一个无序的整型数组arr,找到其中最小的k个数. 方法一: 将数组排序,排序后的数组的前k个数就是最小的k个数. 时间复杂度:O(nlogn) 方法二: 时间复杂度:O(nlogk) 维护 ...
- LeetCode 5071. 找出所有行中最小公共元素(Java)
题目:5071. 找出所有行中最小公共元素 给你一个矩阵 mat,其中每一行的元素都已经按 递增 顺序排好了.请你帮忙找出在所有这些行中 最小的公共元素. 如果矩阵中没有这样的公共元素,就请返回 -1 ...
- 求给定数据中最小的K个数
public class MinHeap { /* * * Top K个问题,求给定数据中最小的K个数 * * 最小堆解决:堆顶元素为堆中最大元素 * * * */ private int MAX_D ...
- 【算法】数组与矩阵问题——找到无序数组中最小的k个数
/** * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) * 过程: * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 * 在堆里的k个元素中堆顶的元素是最小的k个数 ...
- 《程序员代码面试指南》第八章 数组和矩阵问题 找到无序数组中最小的k 个数
题目 找到无序数组中最小的k 个数 java代码 package com.lizhouwei.chapter8; /** * @Description: 找到无序数组中最小的k 个数 * @Autho ...
- 小米笔试题:无序数组中最小的k个数
题目描述 链接:https://www.nowcoder.com/questionTerminal/ec2575fb877d41c9a33d9bab2694ba47?source=relative 来 ...
- Python3求m以内的素数、求m个数中最小的n个数
[本文出自天外归云的博客园] 题1:求m以内的素数(m>2) def find_all_primes_in(m): def prime(num): for i in range(2, num): ...
随机推荐
- 设计模式之Factory
设计模式总共有23种模式这仅仅是为了一个目的:解耦+解耦+解耦...(高内聚低耦合满足开闭原则) 介绍: Factory Pattern有3种当然是全部是creational pattern. 1.S ...
- 我的spring boot,杨帆、起航!
快速新建一个spring boot工程可以去http://start.spring.io/这个网址,配置完后会自动下载一个工程的压缩包,解压后导入相关ide工具即可使用. 工程中会自带一个class启 ...
- Python3 PyPAML 模块(配置文件的操作)
YAML 是专门用来写配置文件的语言,非常简洁和强大 它的基本语法规则如下: 1.大小写敏感 2.使用缩进表示层级关系 3.缩进时不允许使用Tab键,只允许使用空格. 4.缩进的空格数目不重要,只要相 ...
- MACHINE_START与MACHINE_END【转】
转自:http://blog.csdn.net/cxw3506/article/details/8475965 版权声明:本文为博主原创文章,未经博主允许不得转载. 在移植Linux时,有个结构体需要 ...
- Git 常用命令速查表(图文+表格)【转】
转自:http://www.jb51.net/article/55442.htm 一. Git 常用命令速查 git branch 查看本地所有分支git status 查看当前状态 git comm ...
- Java中volatile修饰符,不稳定标记的用法笔记
今天学java特性时,发现了volatile修饰符,这个修饰符修饰的变量告诉java编译器忽略优化机制,这样的优势是: java优化后,寄存器会缓存内存里的变量,另一个线程修改这个变量的内存时,不会同 ...
- STL之顺序容器 deque 动态数组
deque是一个动态数组,deque与vector非常类似,vector是一个单向开口的连续线性空间,deque则是双向开口的连续线性空间.两者唯一的区别是deque可以在数组的开头和末尾插入和删除数 ...
- django-1366, "Incorrect string value: '\\xE6\\x88\\x9A\\xE4\\xBC\\x9F...'
今天把之前的一些代码转移到另外一台电脑的时候, python manage.py syncdb 的时候报了 (1366, "Incorrect string value: '\\xE6\\x ...
- Java Socket编程基础篇
原文地址:Java Socket编程----通信是这样炼成的 Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Sock ...
- Django-form組件補充
自定义验证规则 方法一: 1 2 3 4 5 6 7 8 9 10 from django.forms import Form from django.forms import widgets f ...