我们举例,假若从10000万个数里选出前100个最大的数据。

首先我们先分析:既然要选出前100个最大的数据,我们就建立一个大小为100的堆(建堆时就按找最大堆的规则建立,即每一个根节点都大于它的子女节点),然后再将后面的剩余数据若符合要求就插入堆中,不符合就直接丢弃该数据。

那我们现在考虑:确定是该选择最大堆的数据结构还是最小堆的数据结构呢。

分析一下:

若选用最大堆的话,堆顶是堆的最大值,我们考虑既然要选出从10000万个数里选出前100个最大的数据,我们在建堆的时候,已经考虑了最大堆的特性,那这样的话最大的数据必然在它顶端。假若真不巧,我开始的前100个数据中已经有这10000个数据中的最大值了,那对于我后面剩余的10000-100的元素再想入堆是不是入不进去了!!!所以,选用最大堆从10000万个数里选出前100个最大的数据只能找出一个,而不是100个。

那如果选用最小堆的数据结构来解决,最顶端是最小值,再次遇到比它大的值,就可以入堆,入堆后重新调整堆,将小的值pass掉。这样我们就可以选出最大的前K个数据了。言外之意,假若我们要找出N个数据中最小的前k个数据,就要用最大堆了。

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std; #include<assert.h> void AdjustDown(int* a, int parent, int size)
{
    int child = 2 * parent + 1;
    while (child < size)
    {
        if (child + 1 < size && a[child] > a[child + 1])
        {
            child++;
        }
        if (a[parent]>a[child])
        {
            swap(a[parent], a[child]);
            parent = child;
            child = 2 * parent + 1;
        }
        else
        {
            break;
        }
    }
} void Print(int* a, int size)
{
    cout << "前k个最大的数据:" << endl;
    for (int i = 0; i < size; i++)
    {
        cout << a[i] << "  ";
    }
    cout << endl;
} int* HeapSet(int*a,int N,int K)
{
    assert(a);
    assert(K > 0);
    int* arr = new int[K];
    //将前K个数据保存
    for (int i = 0; i < K; i++)
    {
        arr[i] = a[i];
    }     //建堆
    for (int i = (K-2)/2; i >=0; i--)
    {
        AdjustDown(arr,i,K);
    }      //对剩余的N-K个元素比较大小
    for (int i = K; i < N; i++)
    {
        if (arr[0]<a[i])
        {
            arr[0] = a[i];
            AdjustDown(arr, 0, K);
        }
    }     return arr;
    delete[] arr;
} void Test()
{
    int arr[] = { 12, 2, 10, 4, 6, 8, 54, 67, 25, 178 };
    int k = 5;
    int* ret = HeapSet(arr, sizeof(arr) / sizeof(arr[0]), k);
    Print(ret, k); 
} int main()
{
    Test();
    system("pause");
    return 0;
}

  

由此可以看出,时间复杂度为:K+(K-2)/2*lgn+(N-K)*lgn  -->  O(N)

空间复杂度为:K-->O(1)。

求数组前K个大的数的更多相关文章

  1. MATLAB寻找数组前k个大值

    有时候我们需要寻找数组的前k个大值并按照顺序输出, 在C语言可以通过快速排序等算法,快速求得,这里用matlab写了一个比较简单实用的程序(适用于数组长度不是特别大的情况). function [va ...

  2. [csu/coj 1080]划分树求区间前k大数和

    题意:从某个区间内最多选择k个数,使得和最大 思路:首先题目给定的数有负数,如果区间前k大出现负数,那么负数不选和更大,于是对于所有最优选择,负数不会出现,所以用0取代负数,问题便转化为区间的前k大数 ...

  3. 无序数组中第Kth大的数

    题目:找出无序数组中第Kth大的数,如{63,45,33,21},第2大的数45. 输入: 第一行输入无序数组,第二行输入K值. 该是内推滴滴打车时(2017.8.26)的第二题,也是<剑指of ...

  4. 输出数组里面第N大的数

    好像有些大公司出过面试题:找出数组里面第N大的数,当然有点变化,但本质部分是这样的. 要求是不能排序,时间复杂度不能超过O(n^2) 思路很多,我暂时就只会快排衍生的那种.如果对快速排序不太熟悉了,建 ...

  5. 快速排序及查找第K个大的数。

    本文提供了一种基于分治法思想的,查找第K个大的数,可以使得时间复杂地低于nlogn. 因为快排的平均时间复杂度为nlogn,但是快排是全部序列的排序, 本文查找第k大的数,则不必对整个序列进行排序.请 ...

  6. 认真对待每一道算法题 之 两个排序好的数组寻找的第k个大的数

    转载博客:http://www.cnblogs.com/buptLizer/archive/2012/03/31/2427579.html 题目意思:给出两个排好序的数组 ,不妨设为a,b都按升序排列 ...

  7. [经典] 在未排序数组中返回topK大的数

    解法一,排序 先从大到小快排,然后扫前K个返回 时间复杂度:O(NlogN),空间复杂度O(1) 解法二,优先队列 前K个放入优先队列中,与最小堆顶元素比较大小,若大于则删除堆顶并插入:否则跳过 时间 ...

  8. (算法)Partition方法求数组第k大的数

    如题,下面直接贴出代码: #include <iostream> using namespace std; int Partition(int* A,int left,int right) ...

  9. 【RMQ问题】求数组区间最大值,NYOJ-1185-最大最小值

    转自:http://blog.csdn.net/lilongherolilong/article/details/6624390 先挖好坑,明天该去郑轻找虐 RMQ(Range Minimum/Max ...

随机推荐

  1. Kubernetes生产架构浅谈

    注意 本文,只是笔者针对Kubernetes生产环境运行的一些关于架构设计介绍. 介绍 基于 Kubernetes 系统构建的统一开发运维管控平台.在 Kubernetes 基础上,围绕 微服务系统的 ...

  2. 针对.NET Core, Xamarin以及.NET的自动类型安全Rest库: Refit

    本文大部分内容是针对Refit官网的翻译. 官网地址: https://github.com/reactiveui/refit Refit是一个类似于Retrofit的Restful Api库,使用它 ...

  3. torch_11_风格迁移和cycleGAN

    1,A Neural Algorithm of atistic Style https://axiv.org/pdf/1508.06576.pdf 如何定义图片的内容,风格: 定义内容:在vggnet ...

  4. 一些 Java 和 Android 的参考资料

    1. .net程序员转战android第三篇---登录模块之静态登录 2. .net程序员转战android第二篇---牛刀小试 3. .net程序员转战android第一篇---环境部署 4. 一些 ...

  5. 如何在 Knative 中部署 WebSocket 和 gRPC 服务?

    作者 | 冬岛  阿里云容器平台工程师 导读:虽然说 Knative 默认就支持 WebSocket 和 gRPC,但在使用中会发现,有时想要把自己的 WebSocket 或 gRPC 部署到 Kna ...

  6. A Pattern Language for Parallel Programming

    The pattern language is organized into four design spaces.  Generally one starts at the top in the F ...

  7. 解决基于TypeScript 的 RN项目相对路径引入组件的问题

    一.前言 在开发RN项目时,经常会要使用这样的方式(../../../)来引入组件,感觉非常繁琐,如果项目结构层级比较多,引入的头部更加分不清. 那有没有一种方案和vue项目一样,经过配置后简写路径, ...

  8. MySQL分析数据运行状态利器【show full processlist】

    原文地址:https://www.cnblogs.com/shihuc/p/8733460.html 今天的主角是: SHOW [FULL] PROCESSLIST show full process ...

  9. 转 经典分类网络Googlenet

    转自https://my.oschina.net/u/876354/blog/1637819 2014年,GoogLeNet和VGG是当年ImageNet挑战赛(ILSVRC14)的双雄,GoogLe ...

  10. Winform 窗体皮肤美化_IrisSkin

    1 先把IrisSkin2.dll文件添加到当前项目引用(解决方案资源管理器->当前项目->引用->右键->添加引用,找到IrisSkin2.dll文件.....之后就不用我说 ...