寻找最大的K个数(上)
这是一道很经典的题目,有太多方法了,今天写了两种方法,分别是快排和堆排序
#include <iostream>
using namespace std;
#define N 25 //初始化数组
//int a[] = {6, 2, 3, 9, 4, 3, 1, 2, 4, 4};
//int a[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
int a[] = {, , , , , };
int n = ;
int K = ; //快速排序,o(nlogn),最应该想到的思路,排好序要多大数就输出多大数
/*
partition就是挖第一个洞,从后往前找,找到,挖起来,把前面的洞埋上,再从前往后找,找到,挖起来,把后面的洞埋上,直到最后,high=low了,把这个洞补上
*/
int partition(int* p, int low, int high)
{
int i;
int pivot;
//把第一个数拿出来,挖个洞
pivot = p[low];
while (low < high)
{
//从后往前找,找到比pivot小的值
while (low < high && p[high] >= pivot)
high--;
//然后后面的数埋上前面的洞
//Note这里无须再加个if,因为即使相同了,那我再做一步也无妨,而且也无须把low指针往上移,因为,到时候我可以再判断一次,还是可以移动的
p[low] = p[high]; //从前往后找,找到比pivot大的值,然后把前面的数埋上
while (low < high && p[low] <= pivot)
low++;
p[high] = p[low];
}
//这里low和high已经相同了,所以也可以写成p[high]=pivot,这一步就是把洞埋上
p[low] = pivot;
return low;
}
/*
其实,两个可以写一起,但是,分开写更清楚
quickSort函数就是当low<high时,进行一次partition,然后再对分开的两块进行quickSort
*/
void quickSort(int* p, int low, int high)
{
if(low < high)
{
int breakpoint = partition(p, low, high);
quickSort(p, low, breakpoint - );
quickSort(p, breakpoint + , high);
}
} //堆排序, o(nlogk),考虑到只需取K大的数,那就无须对n个数都排序,只需记录下k个即可
int heap[N];
/*
//这里有点疑问哦,考虑到heap数组可能比较大,所以想定义成全局变量,可是这样就不必传递参数勒,定义成局部变量,参数又太多
目前定义成全局变量
input: lastIndex指heap数组要插入的value的位置(是要插入的位置哦); value指要插入的数字
function: heap数组是从index=0开始储存的,就是把value储存heap数组内,并进行相应的调整,符合最大堆的性质
*/
void MaxHeapPush(int lastIndex, int value)
{
//把value放在堆的末尾
heap[lastIndex] = value;
//记录下末尾的index
int index = lastIndex;
// 不断向上调整
while (index)
{
//若比上面的大,就交换
if (heap[index] > heap[(index - ) / ])
{
int temp = heap[index];
heap[index] = heap[(index - ) / ];
heap[(index - ) / ] = temp;
}
//否则,说明已经调整好了,立即停止
else
break;
//若没有break出来,就要一直调整了,所以index要变动
index = (index - ) / ;
}
}
/*
input:
p数组要初始化数组,提供数据的
n表示该数组的长度,c就是麻烦,连长度都要传入
heapSize表示要维护的堆的大小,Note,一定要大于K哦
*/
void MaxHeapInit(int *p, int n, int heapSize)
{
int i, lastIndex;
lastIndex = ;
for (i = ; i < n; i++)
{
//依次插入
MaxHeapPush(lastIndex, p[i]);
// 若比预定好的堆的大小小的话,最后一个value的值就要增加了
if (lastIndex < heapSize)
lastIndex++;
}
} /*
input: lastIndex是要删除的value的位置(这里千万要注意,其实,跟前面的lastIndex有点不一样)
*/
int MaxHeapPop(int lastIndex)
{
// 交换头尾value
int temp, i;
temp = heap[];
heap[] = heap[lastIndex];
heap[lastIndex] = temp;
// 向下调整
i = ;
int child = * i + ;
while (child < lastIndex)
{
//若有右孩子节点,且右节点比左节点大,那要只需要比较右节点即可
if (child + < lastIndex && heap[ * i + ] > heap[ * i + ])
{
child = child + ;
}
//若孩子节点比父节点大,两个节点交换
if (heap[child] > heap[i])
{
temp = heap[child];
heap[child] = heap[i];
heap[i] = temp;
}
//否则说明已经有序,停止
else
break;
// 变化孩子节点的index
child = * i + ;
}
// 返回末尾value
return heap[lastIndex];
} int main()
{
int i, j;
for (i = ; i < n; i++)
cout<<a[i]<<" ";
cout<<endl;
/*
//快排,若取前K大的数,只需从末尾到前输出K个数即可
quickSort(a, 0, n - 1);
for (i = 0; i < n; i++)
cout<<a[i]<<" ";
cout<<endl;
*/ //注意这里之所以乘以2,是因为只维护K个数字的堆,不能得到前K个大的数!!
MaxHeapInit(a, n, K * - );
for (i = ; i < n; i++)
cout<<heap[i]<<" ";
cout<<endl; // 输出,这里的lastIndex是变化的哦,因为之前维护的2 * K - 1的堆,所以这里也应该是2 * K - 1
for (i = ; i < K; i++)
cout<<MaxHeapPop( * K - - i)<<" ";
cout<<endl; system("pause");
return ;
}
寻找最大的K个数(上)的更多相关文章
- 算法系列:寻找最大的 K 个数
Copyright © 1900-2016, NORYES, All Rights Reserved. http://www.cnblogs.com/noryes/ 欢迎转载,请保留此版权声明. -- ...
- 第2章 数字之魅——寻找最大的K个数
寻找最大的K个数 问题描述 在面试中,有下面的问答: 问:有很多个无序的数,我们姑且假定它们各不相等,怎么选出其中最大的若干个数呢? 答:可以这样写:int array[100] …… 问:好,如果有 ...
- O(N)的时间寻找最大的K个数
(转:http://www.cnblogs.com/luxiaoxun/archive/2012/08/06/2624799.html) 寻找N个数中最大的K个数,本质上就是寻找最大的K个数中最小的那 ...
- 03寻找最小的k个数
题目描述:查找最小的k个元素 题目:输入n个整数,输出其中最小的k个. 例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4. 1:最简单 ...
- 算法练习:寻找最小的k个数
参考July的文章:http://blog.csdn.net/v_JULY_v/article/details/6370650 寻找最小的k个数题目描述:查找最小的k个元素题目:输入n个整数,输出其中 ...
- 编程之美2.5:寻找最大的K个数
编程之美2.5:寻找最大的K个数 引申:寻找第k大的数: 方法一: // 选择第k大的数(通过改进快速排序来实现) public static void SelectShort(int[] array ...
- 寻找最大的k个数问题
这是编程之美书第2.5节的一道题目. 各种解法: 解法一,用nlgn复杂度的排序算法对数组进行从大到小排序,取前K个.但这方法做了两件不必要做的事:它对想得到的K个数进行了排序,对不想得到的n-K个数 ...
- 算法笔记_035:寻找最小的k个数(Java)
目录 1 问题描述 2 解决方案 2.1 全部排序法 2.2 部分排序法 2.3 用堆代替数组法 2.4线性选择算法 1 问题描述 有n个整数,请找出其中最小的k个数,要求时间复杂度尽可能低. 2 ...
- Java实现寻找最小的k个数
1 问题描述 有n个整数,请找出其中最小的k个数,要求时间复杂度尽可能低. 2 解决方案 2.1 全部排序法 先对这n个整数进行快速排序,在依次输出前k个数. package com.liuzhen. ...
随机推荐
- 善待Erlang 代码 -- Xref 实践
Xref 是一个交叉引用工具,通过分析定义的函数间的调用关系,用于查找函数. 模块. 应用程序和版本之间的依赖关系. 通俗而言,Xref 可以检查代码中函数的调用关系.比如在 moduleA 中的 f ...
- mysql master or master copy
双主复制: 在两台server配置my.cnf [root@localhost mysql]# egrep -v "^$|^#" /etc/my.cnf datadir = /my ...
- bzoj 4069~4071 APIO2015
T1 从高到底按位确定答案 A=1时f[i]表示前i个数合法的划分至少需要分出几段,时间复杂度$O(n^2log(ans))$ A>1时f[i][j]表示前i个数划分为j段是否可能合法,转移显然 ...
- Bootstrap-Other:HTML编码规范
ylbtech-Bootstrap-Other:HTML编码规范 1.返回顶部 1. Bootstrap HTML编码规范 语法 用两个空格来代替制表符(tab) -- 这是唯一能保证在所有环境下获得 ...
- Dynamics CRM 2011 权限管理
CRM系统基于角色的权限主要通过部门.角色.用户.团队来进行控制.每一个实体记录的所有者(Owner)必然是某一个用户或团队.一个用户或团队必然归属于一个且只归属于一个部门,但团队的成员即用户可以来自 ...
- c# 之 unsafe
unsafe必须谨慎使用,而且很多时候是不需要unsafe的.通常只有在对性能要求高和与其它模块交互需要用到这个.比如指针操作,无边界检查的数组操作,与一些其他语言编写的模块交互等不安全代码 C#是可 ...
- VUE项目 - IE报vuex requires a Promise polyfill in this browser问题解决
第一步: 安装 babel-polyfill . babel-polyfill可以模拟ES6使用的环境,可以使用ES6的所有新方法 npm install --save babel-polyfill ...
- eclipse-jee-mars-2-win32-x86_64安装activiti
离线安装老是不行,只能在线安装了 选择Activiti BPMN Desisner,然后一直选择下一步,直到出现如下窗体: 幸亏这个插件很小,在线安装也不算慢
- 搭建双系统win10+ubuntu17.10
0. 序言 这里采用先装win10,再装ubuntu的顺序.这样可以避免后面系统启动项设置的问题.都采用UEFI引导方式,且使用usb2.0的u盘来引导(3.0的话,要准备好3.0的驱动).另外注意的 ...
- Oracle 注意点大全
1.索引 经常查询的字段.主表与从表关联主键id必须建立索引.