寻找最大的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. ...
随机推荐
- 遍历树节点(多层)的方法(java)
前序遍历,后序遍历,广度遍历,深度遍历,遍历一级节点.以及按钮如何响应点击事件. import java.awt.*; import java.awt.event.*; import java.uti ...
- 对widget使用WM_SetCallback
当我们对widget使用WM_SetCallback拦截并处理一些消息,可能需要在处理完某些消息后继续调用该Widget原来的callback,典型的例子是WM_DELETE,因为几乎所有widget ...
- [转][Dapper]SQL 经验集
condition.Append(" AND ChineseName like @name"); p.Add("@name", "%" + ...
- Charles 3断点篡改数据
只是临时修改一次网络请求结果,使用重写过于麻烦.对于临时性的修改,最好使用断点. 断点功能主要修改requess和response内容,这个时候接口是在Charles代理层被拦截,还未到手机设备上. ...
- 12步轻松搞定Python装饰器
译者:寒寻 译文:http://www.cnblogs.com/imshome/p/8327438.html 原文:https://dzone.com/articles/understanding-p ...
- 给iOS开发新手送点福利,简述UIPageControl的属性和用法
UIPageControl 1. numberOfPages // 设置有多少页 默认为0 [pageControl setNumberOfPages:kImageCount]; 2. cur ...
- ZOJ-3230-Solving the Problems
/*ZOJ Problem Set - 3230Solving the Problems ------------------------------------------------------- ...
- 接口自动化(二)--操作Excel获取需要数据
这一部分的内容记述一下对Excel表格的操作,本实战中的测试用例是由Excel来管理的,因此操作Excel是重要的一部分. 再次贴出这张图,所有的测试用例都在这个sheet内,请求数据真实存放在jso ...
- OpenCL NativeKernel 计算矩阵乘法
▶ 使用函数 clEnqueueNativeKernel 来调用 C/C++ 本地函数(在 OpenCL 中将其看做回调函数),使用本地编译器(而不是 OpenCL 编译器)来编译和执行内核 ● 代码 ...
- JAVA_03
在Java中,理解JDK.JRE.JVM三者的区别是十分重要的; JDK JDK是Java Development Kit(Java开发工具包)的缩写,包含JRE和其他开发工具. JRE JRE是Ja ...