问题定义

这个问题来自网上看到的百度算法题,感觉很不错,问题定义如下:

假定有20个有序数组,每个数组有500个数字,降序排列,数字类型32位uint数值,现在需要取出这10000个数字中最大的500个,怎么做?

解决方法

这里其实有很多解决方法,笨拙的或者巧妙的。这里介绍一个非常不错的方法,使用最大堆堆排序:

1. 建立大顶堆,维度为数组的个数,这里为20(第一次 插入的是每个数组中最大的值,即第一个元素)。

2. 删除最大堆堆顶,保存到数组或者栈中,然后向最大堆插入删除的元素所在数组的下一个元素。

3. 重复第1,2个步骤,直到删除个数为最大的K个数,这里为500.

代码:

#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <functional>
using namespace std; #define ROWS 20
#define COLS 500 int data[ROWS][COLS]; void CreateData()
{
for(int i=; i<ROWS; i++)
{
for(int j=; j<COLS;j++)
{
data[i][j] = rand(); //生成随机元素
}
}
for( int i=; i<ROWS; i++)
sort(data[i],data[i]+COLS, greater<int>()); //对每一行降序排列
} struct Node
{
int *p; //指向某个列,因为要放入优先队列中,所以要比较大小,就用结构体封装了下
bool operator<(const struct Node &node) const
{
return *p < *node.p;
}
}; void OutMinData( int k)
{
struct Node arr[ROWS];
for(int i=; i<ROWS;i++)
{
arr[i].p = data[i]; //初始化指针指向各行的首位
}
priority_queue<Node > queue( arr, arr+ROWS ); //使用优先队列,默认是大堆 for( int i=; i<k&&i<COLS; i++) //算法核心就是这个循环
{
Node temp = queue.top(); //取出队列中最大的元素
cout << *temp.p << " " <<endl;
queue.pop(); //从队列里删除
temp.p++; //对应行的指针后移
queue.push( temp ); //这里面有log(ROWS)次操作,所以算法的总复杂度为O(klog(20))
} } int main()
{
CreateData(); //生成数据
int k=;
OutMinData( k ); //输出k个元素,这里k不要大于列数COL,可以改进,去掉这个限制,不过会让程序不好懂,就没加
return ;
}

题外话:

上面的是有序数组,但是如果是无序数组呢,可以建立维度为K(这里为500)的最小堆,然后每次删除最小堆的堆顶,直到遍历完所有的数,剩下的就是所求的最大K个数。


N个降序数组,找到最大的K个数的更多相关文章

  1. 每天一道算法题(14)——N个降序数组,找到最大的K个数

     题目: 假定有20个有序数组,每个数组有500个数字,降序排列,数字类型32位uint数值,现在需要取出这10000个数字中最大的500个. 思路 (1).建立大顶堆,维度为数组的个数,这里为20( ...

  2. 【算法】数组与矩阵问题——找到无序数组中最小的k个数

    /** * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) * 过程: * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 * 在堆里的k个元素中堆顶的元素是最小的k个数 ...

  3. [算法]找到无序数组中最小的K个数

    题目: 给定一个无序的整型数组arr,找到其中最小的k个数. 方法一: 将数组排序,排序后的数组的前k个数就是最小的k个数. 时间复杂度:O(nlogn) 方法二: 时间复杂度:O(nlogk) 维护 ...

  4. 《程序员代码面试指南》第八章 数组和矩阵问题 找到无序数组中最小的k 个数

    题目 找到无序数组中最小的k 个数 java代码 package com.lizhouwei.chapter8; /** * @Description: 找到无序数组中最小的k 个数 * @Autho ...

  5. 小米笔试题:无序数组中最小的k个数

    题目描述 链接:https://www.nowcoder.com/questionTerminal/ec2575fb877d41c9a33d9bab2694ba47?source=relative 来 ...

  6. 求一个数组中最小的K个数

    方法1:先对数组进行排序,然后遍历前K个数,此时时间复杂度为O(nlgn); 方法2:维护一个容量为K的最大堆(<算法导论>第6章),然后从第K+1个元素开始遍历,和堆中的最大元素比较,如 ...

  7. [程序员代码面试指南]数组和矩阵问题-找到无序数组中最小的k个数(堆排序)

    题目链接 https://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf?tpId=13&tqId=11182&t ...

  8. 找到数组中最小的k个数

    /*输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字, 则最小的4个数字是1.2.3.4. 示例 1: 输入:arr = [3,2,1], k = ...

  9. [剑指offer]数组中最小的K个数,C++实现

    原创博文,转载请注明出处! http://github.com/wanglei5205 http://cnblogs.com/wanglei5205 # 题目 输入n个整数,找出其中最小的K个数.例如 ...

随机推荐

  1. python3之Django表单(一)

    1.HTML中的表单 在HTML种,表单是在<form>...</form>种的元素,它允许用户输入文本,选择选项,操作对象等,然后发送这些数据到服务器 表单元素允许用户在表单 ...

  2. SQL EXCEPT INTERSECT

    EXCEPT是指在第一个集合中存在,但是不存在于第二个集合中的数据. INTERSECT是指在两个集合中都存在的数据. )) go )) go insert into t1 ,'t1' union a ...

  3. C# DataTable分页函数

    /// <summary> /// 对DataTable进行分页,起始页为1 /// </summary> /// <param name="dt"& ...

  4. u3d 地形 U3d terrain

    u3d 地形 U3d terrain 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:313134555@qq.com E-mail: 313134555 @qq.com fbx ...

  5. Shiro笔记(三)授权

    Shiro笔记(三)授权 一.授权方式 1.编程式: Subject subject=SecurityUtils.getSubject(); if(subject.hasRole("root ...

  6. Redis管道理解

    Redis管道理解 简介 管道并不是Redis本身提供的功能,通常是客户端提供的功能: 管道就是打包多条无关命令批量执行,以减少多个命令分别执行消耗的网络交互时间(TCP网络交互),可以显著提升Red ...

  7. 在eclipse总是会运行之前的错误项目

    我改了context root没有用,删了work下面的项目文件也没有用,最后必须要改server的配置,就是在windows下有个server runtimeEnvironment http://b ...

  8. php中静态方法的使用

    静态方法 (1)静态方法不能访问这个类中的普通属性,因为那些属性属于一个对象,但可以访问静态属性: (2)从当前类(不是子类)中访问静态方法或属性,可以使用 self 关键字,self 指向当前类,就 ...

  9. 毫秒转时间(java.js)

    SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); GregorianCalendar gc ...

  10. tcp连接状态查看

    linux常用查看tcp状态工具netstat和ss,这两个工具查看时都有1个Recv-Q和Send-Q 解释如下: 对应处于Listen状态的套接字: Recv-Q表示已建立连接队列中连接个数(等待 ...