每天一道算法题(14)——N个降序数组,找到最大的K个数
题目:
假定有20个有序数组,每个数组有500个数字,降序排列,数字类型32位uint数值,现在需要取出这10000个数字中最大的500个。
思路
(1).建立大顶堆,维度为数组的个数,这里为20(第一次
插入的是每个数组中最大的值,即第一个元素)。
(2).删除最大堆堆顶,保存到数组或者栈中,然后向最大堆插入删除的元素所在数组的下一个元素。
(3).重复第1,2个步骤,直到删除个数为最大的K个数,这里为500.
代码
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std; #define ROWS 20
#define COLS 500 int data[ROWS][COLS]; void CreateData()
{
for(int i=0; i<ROWS; i++)
for(int j=0; j<COLS;j++)
data[i][j] = rand(); //生成随机元素
for( int i=0; i<ROWS; i++)
sort(data[i],data[i]+COLS, greater<int>()); //对每一行降序排列
}
//十分重要
struct Node
{
int *p; //指向某个列,因为要放入优先队列中,所以要比较大小,就用结构体封装了下
bool operator<(const Node &node) const
{
return *p < *node.p;
}
}; void OutMinData( int k)
{
struct Node arr[ROWS];
for(int i=0; i<ROWS;i++)
arr[i].p = data[i]; //初始化指针指向各行的第1列的地址
priority_queue<Node > queue( arr, arr+ROWS ); //使用优先队列,默认是大堆,此时需要调用node定义中的“<”重载函数 for( int i=0; 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=500;
OutMinData( k ); //输出k个元素,这里k不要大于列数COL,可以改进,去掉这个限制,不过会让程序不好懂,就没加
return 0;
}
分析
(1),压入大顶堆的元素为Node类型。因此创建大根堆时,需要重载“<”函数
(2).每次弹出最大值,压入新的值时。最多需要调整log(20)次,因此总共时间复杂度为O(500*log(20))
(3).sort()默认升序排列,因此需要加入仿函数greater<int>
(4)data[i]+j==&data[i][j]==*(data+i)+j,&data[i]==data+i
扩展
倘若非已经排序好的元素的同样数组求最大的前k个数。可以建立高度为log(k)的小根堆。遍历所有数组,每次删除根节点即最小的值,加入节点调整堆。时间复杂度为O(10000*log(500))
参考:
每天一道算法题(14)——N个降序数组,找到最大的K个数的更多相关文章
- 《github一天一道算法题》:分治法求数组最大连续子序列和
看书.思考.写代码. /*************************************** * copyright@hustyangju * blog: http://blog.csdn. ...
- 【算法题 14 LeetCode 147 链表的插入排序】
算法题 14 LeetCode 147 链表的插入排序: 解题代码: # Definition for singly-linked list. # class ListNode(object): # ...
- 算法题14 小Q歌单,牛客网,腾讯笔试题
算法题14 小Q歌单,牛客网,腾讯笔试题 题目: 小Q有X首长度为A的不同的歌和Y首长度为B的不同的歌,现在小Q想用这些歌组成一个总长度正好为K的歌单,每首歌最多只能在歌单中出现一次,在不考虑歌单内歌 ...
- 每天一道算法题(4)——O(1)时间内删除链表节点
1.思路 假设链表......---A--B--C--D....,要删除B.一般的做法是遍历链表并记录前驱节点,修改指针,时间为O(n).删除节点的实质为更改后驱指针指向.这里,复制C的内容至B(此时 ...
- [算法]找到无序数组中最小的K个数
题目: 给定一个无序的整型数组arr,找到其中最小的k个数. 方法一: 将数组排序,排序后的数组的前k个数就是最小的k个数. 时间复杂度:O(nlogn) 方法二: 时间复杂度:O(nlogk) 维护 ...
- 从一道算法题实现一个文本diff小工具
众所周知,很多社区都是有内容审核机制的,除了第一次发布,后续的修改也需要审核,最粗暴的方式当然是从头再看一遍,但是编辑肯定想弄死你,显然这样效率比较低,比如就改了一个错别字,再看几遍可能也看不出来,所 ...
- 【每天一道算法题】时间复杂度为O(n)的排序
有1,2,……一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度为O(1),使用交换,而且一次只能交换两个数. 这个是以前看到的算法题,题目不难.但是要求比较多,排序算法中,时间 ...
- 每天一道算法题-leetcode136-只出现一次的数字
前言 打卡第一天 2019.10.26日打卡 算法,即解决问题的方法.同一个问题,使用不同的算法,虽然得到的结果相同,但是耗费的时间和资源是不同的.这就需要我们学习算法,找出哪个算法更好. 大家都知道 ...
- 提前批笔试一道算法题的Java实现
题目描述 这是2021广联达校招提前批笔试算法题之一. 我们希望一个序列中的元素是各不相同的,但是理想和显示往往是有差距的.现在给出一个序列A,其中难免有相同的元素,现在提供了一种变化方式,使得经过若 ...
随机推荐
- Android在layout xml中使用include完成静态加载
Android在layout xml中使用include完成静态加载 include静态加载:不仅可以加载布局,还可以加载控件(控件标签名要在最外层)include标签中有个layout属性就是专门用 ...
- java中i=i++问题分析
http://www.ticmy.com/?p=43 重点:局部变量表 和 操作数栈的执行过程. 使用javac编译后再使用javap -c Test反编译这个类查看它的字节码,如下(只摘取main方 ...
- android里getView,inflate,listview问题
今天在写一个listview的时候,遇到一个问题,如下 package com.brookji.funlearn; import java.util.ArrayList; import android ...
- oracle Data blocks,Extents,Segments
转载 先看Data blocks(也叫逻辑块,oracle块,页)吧,oracle存储数据都是在这些数据块中,一个数据块是磁盘上数据库物理空间一系列物理字节的组成. 比Data blocks更高 ...
- 【WPF】推荐一款拖拉缩放控件的DEMO
引言 在CodeProject上有个实现了控件拖拉缩放的DEMO,界面很漂亮,里面对Thumb和Adorner运用得很精彩.我觉得,使用WPF的开发者都可以去学习一下.下面放出链接. WPF Diag ...
- Django 基础 ORM系统
Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据 ...
- 机械硬盘运行VMWare虚拟机太卡的解决办法
VMWare有个运行机制是:在硬盘生成内存的镜像文件以降低内存的使用量,而这个是可以配置的,如果你的内存足够大的话,就可以不使用这个内存镜像,从而提高运行效率:配置方法如下: 1.单个虚拟机的配置,修 ...
- spark 稠密向量和稀疏向量
Spark mlib的本地向量有两种: DenseVctor :稠密向量 其创建方式 Vector.dense(数据) SparseVector :稀疏向量 其创建方式有两种: 方法一 ...
- UVA 11291 Smeech
[来源]https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- PHP中不用第三个变量交换两个变量的值
相信大家在PHP面试或者学习中经常会遇到这个问题就是“不用第三个变量来交换两个变量的值”,今天正对这个问题来讨论一下: 第一种方法:首先会想到的 这种方法简单可行,顺利的交换了两个变量的值. 第二种方 ...