编程之美——最大的k个数

方法一:使用快速排序划分函数partion将数组分为两组:sa和sb
            (1)若sa组的个数大于K,则继续在sa分组中找取最大的K个数字 。
            (2)若sa组中的数字小于K ,其个数为num,则继续在sb中找取 K-num个最大数字 。

复杂度:N*log2(K);

类似快速排序的partition过程,当参考值随机选取时,复杂度为O(N)

具体参考:http://blog.csdn.net/v_JULY_v/article/details/6370650
   具体代码:

 1 #include<iostream>
 2 #include<stdlib.h>
 3 #include<time.h>
 4 using namespace std;
 5
 6 const int N=6;
 7 const int K=4;
 8
 9 int findk(int arr[],int low,int high,int k);
10 int partion(int arr[],int low,int high);
11
12 int main()
13 {
14     int arr[N]={6,3,8,9,4,5};
15
16     findk(arr,0,N-1,K);
17
18     for(int i=0;i<K;++i)
19         cout<<arr[i]<<ends;
20
21     return 0;
22 }
23
24 int findk(int arr[],int low,int high,int k)
25 {
26     if(low<=high)
27     {
28         int num=partion(arr,low,high);
29         if((num+1)==k)
30             return num;
31         if((num+1)>k)
32             return findk(arr,low,num-1,k);
33         else if((num+1)<k)
34             return findk(arr,num+1,high,k-1-num);
35     }
36 }
37
38 int partion(int arr[],int low,int high)
39 {
40     int tmp=arr[low];
41
42     while(low<high)
43     {
44         while(arr[high]<tmp&&low<high)
45             --high;
46         if(arr[high]>tmp)
47         {
48             arr[low]=arr[high];
49             ++low;
50         }
51         while(arr[low]>tmp&&low<high)
52             ++low;
53         if(arr[low]<tmp)
54         {
55             arr[high]=arr[low];
56             --high;
57         }
58     }
59     arr[low]=tmp;
60     return low;
61 }

方法二:若数据元素很多,不能全部装入内存,可以维持容量为K的最小化堆,堆顶元素就是最大的K个数中的最小数,扫描整个数据;

a.若扫描到的数据大于堆顶元素,替换堆顶元素,更新堆,复杂度(log2(K));

b.若小于,则维持堆不变;

c.扫描下一元素,重复a,b;最后输出堆中元素

算法复杂度:N*log2(K);

具体代码:

  1 #include<iostream>
  2 using namespace std;
  3
  4 const int N=10;
  5 const int K=5;
  6 int arr[N]={6,3,8,9,4,5,11,34,7,1};
  7
  8 template<class T>
  9 class minHeap
 10 {
 11 private:
 12     int maxSize;
 13     int currentSize;
 14     T *heapArray;
 15 public:
 16     minHeap();
 17     void buildHeap();
 18     void shiftDown(int position);
 19     T deheap();
 20     void outheap();
 21     void setheap(const T &x);
 22     virtual ~minHeap()
 23     {
 24         delete [] heapArray;
 25     }
 26 };
 27
 28 template<class T>
 29 minHeap<T>::minHeap()
 30 {
 31     currentSize=0;
 32     //heapArray[0] is empty
 33     maxSize=K+1;
 34     heapArray=new T[maxSize];
 35     for(int i=0;i<K;++i)
 36         heapArray[i+1]=arr[i];
 37     currentSize=K;
 38     buildHeap();
 39 }
 40
 41 template<class T>
 42 void minHeap<T>::buildHeap()
 43 {
 44     for(int i=currentSize/2;i>0;--i)
 45         shiftDown(i);
 46 }
 47
 48 template<class T>
 49 void minHeap<T>::shiftDown(int position)
 50 {
 51     int p=position;
 52     int pnum=heapArray[p];
 53     int pson=2*p;
 54
 55     while(pson<=currentSize)
 56     {
 57         //the small one
 58         if(pson!=currentSize&&heapArray[pson]>heapArray[pson+1])
 59             ++pson;
 60         if(heapArray[p]>heapArray[pson])
 61         {
 62             heapArray[p]=heapArray[pson];
 63             p=pson;
 64             pson=2*p;
 65         }
 66         else
 67             break;
 68     }
 69     heapArray[p]=pnum;
 70 }
 71
 72 template<class T>
 73 T minHeap<T>::deheap()
 74 {
 75     return heapArray[1];
 76 }
 77
 78 template<class T>
 79 void minHeap<T>::outheap()
 80 {
 81     for(int i=1;i<=K;++i)
 82         cout<<heapArray[i]<<ends;
 83 }
 84
 85 template<class T>
 86 void minHeap<T>::setheap(const T &x)
 87 {
 88     heapArray[1]=x;
 89     buildHeap();
 90 }
 91
 92 int main()
 93 {
 94     minHeap<int> heap;
 95
 96     for(int i=4;i<9;++i)
 97     {
 98         if(arr[i]>heap.deheap())
 99             heap.setheap(arr[i]);
100         else
101             continue;
102     }
103
104     heap.outheap();
105
106     return 0;
107 }

编程之美——最大的k个数

时间: 2024-11-06 07:17:13

编程之美——最大的k个数的相关文章

编程之美中1的个数的问题

//采用最直接的方法,时间复杂度为O(N*logN): /*#include <iostream> #include<typeinfo> #include<specstrings.h> #include<string> using namespace std; int num_one(int n) { int count=0; while(n) { count+=(n%10==1)?1:0; n/=10; } return count; } int core

【编程之美】2.5 寻找最大的k个数

有若干个互不相等的无序的数,怎么选出其中最大的k个数. 我自己的方案:因为学过找第k大数的O(N)算法,所以第一反应就是找第K大的数.然后把所有大于等于第k大的数取出来. 写这个知道算法的代码都花了2个多小时,反思,太慢了. 注意边界条件,不要混混沌沌的. /************我自己的解法*****************/ //选择数组a[N]中最大的第k个数 int Select(int * a, int N, int k) { if(k > N || a == NULL) { cou

编程之美之2.5 寻找最大的K个数

[题目] 有很多无序的数,从中找出最大的K个数.假定他们都不相等. [解法一] 如果数据不是很多,例如在几千个左右,我们可以排一下序,从中找出最大的K个数.排序可以选择快速排序或者堆排序 [cpp] view plaincopy #include<stdio.h> #include<stdlib.h> int cmp(const void *a,const void *b){ return *(int *)a - *(int *)b; } int main(){ int n,k;

编程之美之寻找最大的k个数

这个题目很常见,方法也很多,这里总结了编程之美给出的几个比较好的方法,也算是对这个问题的一个总结. 方法一.partition算法,每次partition的复杂度为O(n),总的平均时间复杂度为O(nlogn) 分析:运用partition算法,如果返回的provit > k-1,则说明要找的数都在前面,把end= provit-1;如果provit < k-1,表明找到一部分,先把部分数据保存,然后start = provit + 1;如果正好相等,则保存后结束,具体代码如下: int pa

编程之美-1的个数

1的数目 题目:给定一个十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现所有"1"的个数. 例如: N=2,写下1~2.这样只出现了1个"1". N=12,我们会写下1,2,3,4,5,6,7,8,9,10,11,12,这样,1的个数是5. 问题是: 1.写一个函数F(N),返回1到N之间出现的"1"的个数,比如F(12)=5; 2.满足条件"F(N)=N"的最大的N是多少?   我们就先来看看问题1的解法吧:

编程算法 - 最小的k个数 代码(C)

最小的k个数 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入n个整数, 找出其中的最小k个数. 使用快速排序(Quick Sort)的方法求解, 把索引值(index)指向前k个数. 代码: /* * main.cpp * * Created on: 2014.6.12 * Author: Spike */ /*eclipse cdt, gcc 4.8.1*/ #include <stdio.h> #include <stdl

编程算法 - 最小的k个数 红黑树 代码(C++)

最小的k个数 红黑树 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入n个整数, 找出其中的最小k个数. 使用红黑树(multiset), 每次替换最大的值, 依次迭代. 时间复杂度: O(nlogk). 代码: /* * main.cpp * * Created on: 2014年6月29日 * Author: wang */ #include <iostream> #include <vector> #includ

求二进制数中1的个数(编程之美)

求二进制数中1的个数 继京东618店庆时买的<编程之美>这本书,翻了翻,发现里面的题还是挺有意思的,看起来我们觉得很简单的题目,解法却有很多很多种,真是一个比一个巧妙,于是,决定记录一下. 书中的题目如下 对于一个字节(8bit)的无符号数,求其二进制表示中"1"的个数,要求算法的执行效率尽可能高. 就像书中给我们说的一样,我们一般人可能想到的解决方法如下 int countOne(int n){ int count=0; while(n){ if(n%2==1){ cou

编程之美——二进制数中1的个数

解法一:若二进制末尾为1,则除以2余1: int count(int a) { int num=0; while(a) { if(a%2==1) ++num; a=a/2; } return num; } 解法二:使用移位操作相除: int count(int a) { int num=0; while(a) { num+=a&0x01; a>>=1; } return num; } 解法三:以上两种算法复杂度log2(t),t为a的二进制表示位数,若要求复杂度仅与二进制表示中1的个数