寻找最大的K个数(下)
接着昨天的写,里面的代码包含昨天的
1 #include <iostream> 2 using namespace std; 3 #define N 50 4 5 //初始化数组 6 int a[] = {6, 2, 3, 4, 4, 3, 1, 2, 4, 4}; 7 //int a[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; 8 //int a[] = {1, 2, 3, 4, 5, 6}; 9 //int a[] = {6, 2, 3, 9, 4, 10, 1, 20, 40, 5}; 10 int n = 10; 11 int K = 4; 12 13 //快速排序,o(nlogn),最应该想到的思路,排好序要多大数就输出多大数 14 /* 15 partition就是挖第一个洞,从后往前找,找到,挖起来,把前面的洞埋上,再从前往后找,找到,挖起来,把后面的洞埋上,直到最后,high=low了,把这个洞补上 16 */ 17 int partition(int* p, int low, int high) 18 { 19 int i; 20 int pivot; 21 //把第一个数拿出来,挖个洞 22 pivot = p[low]; 23 while (low < high) 24 { 25 //从后往前找,找到比pivot小的值 26 while (low < high && p[high] <= pivot) 27 high--; 28 //然后后面的数埋上前面的洞 29 //Note这里无须再加个if,因为即使相同了,那我再做一步也无妨,而且也无须把low指针往上移,因为,到时候我可以再判断一次,还是可以移动的 30 p[low] = p[high]; 31 32 //从前往后找,找到比pivot大的值,然后把前面的数埋上 33 while (low < high && p[low] >= pivot) 34 low++; 35 p[high] = p[low]; 36 } 37 //这里low和high已经相同了,所以也可以写成p[high]=pivot,这一步就是把洞埋上 38 p[low] = pivot; 39 return low; 40 } 41 /* 42 其实,两个可以写一起,但是,分开写更清楚 43 quickSort函数就是当low<high时,进行一次partition,然后再对分开的两块进行quickSort 44 */ 45 void quickSort(int* p, int low, int high) 46 { 47 if(low < high) 48 { 49 int breakpoint = partition(p, low, high); 50 quickSort(p, low, breakpoint - 1); 51 quickSort(p, breakpoint + 1, high); 52 } 53 } 54 55 //堆排序, o(nlogk),考虑到只需取K大的数,那就无须对n个数都排序,只需记录下k个即可 56 int heap[N]; 57 /* 58 //这里有点疑问哦,考虑到heap数组可能比较大,所以想定义成全局变量,可是这样就不必传递参数勒,定义成局部变量,参数又太多 59 目前定义成全局变量 60 input: lastIndex指heap数组要插入的value的位置(是要插入的位置哦); value指要插入的数字 61 function: heap数组是从index=0开始储存的,就是把value储存heap数组内,并进行相应的调整,符合最大堆的性质 62 */ 63 void MaxHeapPush(int lastIndex, int value) 64 { 65 //把value放在堆的末尾 66 heap[lastIndex] = value; 67 //记录下末尾的index 68 int index = lastIndex; 69 // 不断向上调整 70 while (index) 71 { 72 //若比上面的大,就交换 73 if (heap[index] > heap[(index - 1) / 2]) 74 { 75 int temp = heap[index]; 76 heap[index] = heap[(index - 1) / 2]; 77 heap[(index - 1) / 2] = temp; 78 } 79 //否则,说明已经调整好了,立即停止 80 else 81 break; 82 //若没有break出来,就要一直调整了,所以index要变动 83 index = (index - 1) / 2; 84 } 85 } 86 /* 87 input: 88 p数组要初始化数组,提供数据的 89 n表示该数组的长度,c就是麻烦,连长度都要传入 90 heapSize表示要维护的堆的大小,Note,一定要大于K哦 91 */ 92 void MaxHeapInit(int *p, int n, int heapSize) 93 { 94 int i, lastIndex; 95 lastIndex = 0; 96 for (i = 0; i < n; i++) 97 { 98 //依次插入 99 MaxHeapPush(lastIndex, p[i]); 100 // 若比预定好的堆的大小小的话,最后一个value的值就要增加了 101 if (lastIndex < heapSize) 102 lastIndex++; 103 } 104 } 105 /* 106 input: lastIndex是要删除的value的位置(这里千万要注意,其实,跟前面的lastIndex有点不一样) 107 */ 108 int MaxHeapPop(int lastIndex) 109 { 110 // 交换头尾value 111 int temp, i; 112 temp = heap[0]; 113 heap[0] = heap[lastIndex]; 114 heap[lastIndex] = temp; 115 // 向下调整 116 i = 0; 117 int child = 2 * i + 1; 118 while (child < lastIndex) 119 { 120 //若有右孩子节点,且右节点比左节点大,那要只需要比较右节点即可 121 if (child + 1 < lastIndex && heap[2 * i + 2] > heap[2 * i + 1]) 122 { 123 child = child + 1; 124 } 125 //若孩子节点比父节点大,两个节点交换 126 if (heap[child] > heap[i]) 127 { 128 temp = heap[child]; 129 heap[child] = heap[i]; 130 heap[i] = temp; 131 } 132 //否则说明已经有序,停止 133 else 134 break; 135 // 变化孩子节点的index 136 child = 2 * i + 1; 137 } 138 // 返回末尾value 139 return heap[lastIndex]; 140 } 141 142 //快排的优化,时间复杂度还是o(nlogn),但是时间会大大减少 143 /* 144 由于只需要知道前K大数,没必要把所有的数都进行排序,而快排的思想就是找到一个值一分为二,所以,我们正好利用这一点 145 有了之前写好的partition函数,实现起来就就是方便!! 146 */ 147 void optQuickSort(int* p, int low, int high, int k) 148 { 149 int cur = partition(p, low, high); 150 if (cur - low > k) 151 optQuickSort(p, low, cur - 1, k); 152 else if (cur - low < k - 1) 153 optQuickSort(p, cur + 1, high, k - (cur - low + 1)); 154 } 155 156 //部分排序,o(nK) 157 /* 158 这本应该最新想到的呀,若K=1,其实就只需找最大值就好了 159 当K<logn时,才有用武之地呀 160 */ 161 void partSort(int* p, int n, int k) 162 { 163 int i, j, maxI, temp; 164 for (i = 0; i < k; i++) 165 { 166 maxI = i; 167 for (j = i; j < n; j++) 168 { 169 if (p[j] > p[maxI]) 170 maxI = j; 171 } 172 if (i != maxI) 173 { 174 temp = p[maxI]; 175 p[maxI] = p[i]; 176 p[i] = temp; 177 } 178 } 179 } 180 181 //时间换空间的办法,o(n) 182 /* 183 适用于整数,且范围不是很大的情况 184 如果没有重复的话,还可以用bit数组 185 */ 186 void findCount(int*p, int n, int k) 187 { 188 int count[N] = {0}; 189 int i, j, sumCount; 190 //首先先对输入的元素进行计数 191 for (i = 0; i < n; i++) 192 { 193 count[p[i]] += 1; 194 } 195 sumCount = 0; 196 for (i = N - 1; i > 0; i--) 197 { 198 sumCount += count[i]; 199 //若累计最大的数大于k了,就把多余的部分去掉,把最大的k个数输出 200 if (sumCount > k) 201 { 202 for (j = 0; j < count[i] - (sumCount - k); j++) 203 cout<<i<<" "; 204 break; 205 } 206 //若累计的没有到达K,那就直接输出啦 207 else 208 { 209 for (j = 0; j < count[i]; j++) 210 cout<<i<<" "; 211 } 212 } 213 } 214 215 int main() 216 { 217 int i, j; 218 for (i = 0; i < n; i++) 219 cout<<a[i]<<" "; 220 cout<<endl; 221 /* 222 //快排,若取前K大的数,只需从末尾到前输出K个数即可 223 quickSort(a, 0, n - 1); 224 for (i = 0; i < n; i++) 225 cout<<a[i]<<" "; 226 cout<<endl; 227 228 //注意这里之所以乘以2,是因为只维护K个数字的堆,不能得到前K个大的数!! 229 MaxHeapInit(a, n, K * 2 - 1); 230 for (i = 0; i < n; i++) 231 cout<<heap[i]<<" "; 232 cout<<endl; 233 // 输出,这里的lastIndex是变化的哦,因为之前维护的2 * K - 1的堆,所以这里也应该是2 * K - 1 234 for (i = 0; i < K; i++) 235 cout<<MaxHeapPop(2 * K - 1 - i)<<" "; 236 cout<<endl; 237 238 optQuickSort(a, 0, n - 1, K); 239 240 partSort(a, n, K); 241 for (i = 0; i < n; i++) 242 cout<<a[i]<<" "; 243 cout<<endl; 244 */ 245 findCount(a, n, K); 246 system("pause"); 247 return 0; 248 }
转载于:https://www.cnblogs.com/chuanlong/p/3708724.html
寻找最大的K个数(下)相关推荐
- 编程之美2.5 寻找最大的K个数
在一个数组中寻找最大的K个数,我们首先说一种非常简单的方法,利用快速排序中的分割算法,即我们经常看见的partition.这个函数会返回一个 int 类型的值,这个值代表的是前一半数字和后一半数字的分 ...
- 编程之美-寻找最大的k个数
[问题描述] 有很多无序的数,我们姑且假定它们各不相等,怎么选出其中最大的若干个数呢? 方法一:时间复杂度min(O(nlogn), O(nk)) idea 1: 先用快速排序或者堆排序进行排序,然后 ...
- 程序员编程艺术:第三章、寻找最小的k个数
程序员编程艺术:第三章.寻找最小的k个数 作者:July. 时间:二零一一年四月二十八日. 致谢:litaoye, strugglever,yansha,luuillu,Sorehead,及狂想曲创作 ...
- 算法题解之寻找最大的k个数
一般看到寻找最大的k个数的题目,我们第一想法便是先使用降序排序,然后取前k个即可,这种方法确实是比较常规的,一般情况下也是可行的,但是如果数据十分庞大,则会影响使得创建的数组内存溢出等等.因此,需要对 ...
- 海量数据中,寻找最小的k个数。
维护k个元素的最大堆,即用容量为k的最大堆存储最小的k个数,k1设为大顶堆中最大元素.遍历一次数列,n,每次遍历一个元素x,与堆顶元素比 较,x<kmax,更新堆,否则不更新堆. 1 // 海量 ...
- 寻找最大的k个数问题
这是编程之美书第2.5节的一道题目. 各种解法: 解法一,用nlgn复杂度的排序算法对数组进行从大到小排序,取前K个.但这方法做了两件不必要做的事:它对想得到的K个数进行了排序,对不想得到的n-K个数 ...
- 寻找最大的K个数(上)
这是一道很经典的题目,有太多方法了,今天写了两种方法,分别是快排和堆排序 1 #include <iostream> 2 using namespace std; 3 #define N ...
- Java实现寻找最小的k个数
1 问题描述 有n个整数,请找出其中最小的k个数,要求时间复杂度尽可能低. 2 解决方案 2.1 全部排序法 先对这n个整数进行快速排序,在依次输出前k个数. package com.liuzhen. ...
- java第k大的数字,JAVA中寻找最大的K个数解法
这个题拿到之后首先会想到排序,排好序之后在选取选取最大的K个数.排序选择快速排序是个比较好的选择. 好了,让我们来进行第一个解法:快速排序 代码如下 复制代码代码如下: public static v ...
最新文章
- 【问题收录】INSTALL_FAILED_NO_MATCHING_ABIS
- 图的顺序存储结构及C语言实现
- 设置select默认值
- 使用 mitmproxy + python 做拦截代理
- 【401天】跃迁之路——程序员高效学习方法论探索系列(实验阶段158-2018.03.13)...
- 8086汇编学习小记-1
- gtk-vnc linux,vncviewer远程链接桌面linux
- 计算机 术语库 excel,Trados直接用Excel做术语库
- DedeCMS 5.7 后门漏洞
- eclipse必备的15的个快捷键
- C#检测ocx控件是否注册
- ATSC和DVB数字电视系统的比较
- 如何举报YouTube视频和评论
- 迪拜政府和当地银行合作推出基于区块链的贷款平台
- 交叉编译ffmpeg
- 微信小程序之实现到商品列表跳转商品详情页
- STC12C5A60S2单片机驱动超声波
- python List中删除特定元素
- ecg 幅度_ECG信号
- TI CC2540 USB CDC Serial Port驱动安装失败原因及解决方法