Description:

两个长度为 n 的数组 A 和 B, 各从中选出一个元素相加 A[i] + B[j], 求 top n 小的那些和。

思路 1:这样的和总共有 n^2 个, 排序,然后取前 n 个。

时间复杂度 O(n^2 lgn), 空间复杂度 O(n^2)

思路 2:用 最大堆

     1. 首先用 n 个和建立一个最大堆,

     2. 然后循环剩余的 n^2 - n 个和,依次与堆顶元素比较(最大值), 如果小于最大值,则弹出堆顶,push 进入当前的和。

         时间复杂度 O(n^2 lgn), 空间复杂度是 O(n)

思路3: 还是采用 最小堆,并采用 多路合并 的思路。

首先,分析多路合并问题: 把 K 个有序数组合并成一个数组。

1. 将 K 个数组的首元素(最小),建立一个最小堆;

     2. 弹出最小值,并插入新的数组中;将最小值所在的数组的下一个元素插入堆中。这样依次执行下去。

      多路合并的代码见 http://blog.csdn.net/shoulinjun/article/details/19576585



回到我们的问题,将 N^2 个 sum 写成如下的形式:

所有 N^2 个和:(数组 A 和 B 排序后)

A[0] + B[0] <= A[0] + B[1] <= A[0] + B[2] <= ... <= A[0] + B[n-1]

A[1] + B[0] <= A[1] + B[1] <= A[1] + B[2] <= ... <= A[1] + B[n-1]

...............................

A[n-1] + B[0] <= A[n-1] + B[1] <= A[n-1] + B[2] <= ... <= A[n-1] + B[n-1]

注意: 第一步将数组 A 和 B 排序,则上述的 N 个序列都是有序的。

Bingo! 这时就可以采用与 多路合并 同样的算法:

Algorithm:

1. 将数组 A 和 B 排序

     2. 用 上述 N 个序列的首元素(最小),建立一个最小堆;

     3. 弹出最小值,即为 top N;将最小值所在的数组的下一个元素插入堆中。这样执行 N 次, 得到 所有的 top N

Complexity:

O(NlgN) + O(N)+ N*O(lgN) = O(NlgN)

Implementation:

实现细节的话,算法的第 2 步中, 最小值所在的数组的下一个元素如何得到?? 可以同时记录最小值这个和中所包含的B 中元素的下标。

下一个元素的值就是 min - B[i] + B[i+1]

  1. //copyright @ L.J.SHOU Feb.14, 2014
  2. #include <iostream>
  3. #include <vector>
  4. #include <utility>
  5. #include <queue>
  6. #include <algorithm>
  7. #include <iterator>
  8. using namespace std;
  9.  
  10. //A and B have the same size K
  11. vector<int> TopKSum(vector<int> &A, vector<int> &B)
  12. {
  13. vector<int> result;
  14. priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > Q;
  15.  
  16. /* sort */
  17. sort(A.begin(), A.end());
  18. sort(B.begin(), B.end());
  19.  
  20. for(int i=0; i<A.size(); ++i)
  21. Q.push(make_pair(A[i] + B[0], 0)); /* 0 denotes index in B */
  22.  
  23. for(int i=0; i<A.size(); ++i)
  24. {
  25. pair<int, int> e = Q.top(); Q.pop();
  26.     result.push_back(e.first);
  27.     /* push next element back into heap */
  28.     e.first = e.first - B[e.second] + B[e.second+1];
  29.     e.second ++;
  30.     Q.push(e);
  31. }
  32.  
  33. return result;
  34. }
  35.  
  36. int main(void)
  37. {
  38. vector<int> A, B, sum;
  39. A.push_back(1);
  40. A.push_back(2);
  41. A.push_back(3);
  42.  
  43. B.push_back(2);
  44. B.push_back(4);
  45. B.push_back(4);
  46.  
  47. sum = TopKSum(A, B);
  48. /* print vector */
  49. copy(sum.begin(), sum.end(), ostream_iterator<int>(cout, " "));
  50. cout << endl;
  51.  
  52. return 0;
  53. }

思考题:

n 个长度为 n 的数组,每个数组中选出一个元素相加, 求 top n 小的那些 sum。

复杂度: n^2 lgn

算法----序列和的 top N的更多相关文章

  1. 【机器学习】支持向量机(SVM)的优化算法——序列最小优化算法(SMO)概述

    SMO算法是一一种启发式算法,它的基本思路是如果所有变量的解的条件都满足最优化问题的KKT条件,那么这个最优化问题的解就得到了.因为KKT条件是该优化问题的充分必要条件. 整个SMO算法包括两个部分: ...

  2. MapReduce算法形式五:TOP—N

    案例五:TOP—N 这个问题比较常见,一般都用于求前几个或者后几个的问题,shuffle有一个默认的排序是正序的,但如果需要逆序的并且暂时还不知道如何重写shuffle的排序规则的时候就用以下方法就行 ...

  3. 经典算法(一) top k

    问题:1亿数据中,找出最大的k个数,要求使用内存不超过1m (延伸问题:1亿数据中,找出重复出现次数最多的k个,要求使用内存不超过1m 等) 分析: 1亿数字(int)占内存:100000000 * ...

  4. 必考算法之 Top K 问题

    大家好,这里是<齐姐聊算法>系列之 Top K 问题. Top K 问题是面试中非常常考的算法题. 8 Leetcode 上这两题大同小异,这里以第一题为例. 题意: 给一组词,统计出现频 ...

  5. Top K问题的两种解决思路

    Top K问题在数据分析中非常普遍的一个问题(在面试中也经常被问到),比如: 从20亿个数字的文本中,找出最大的前100个. 解决Top K问题有两种思路, 最直观:小顶堆(大顶堆 -> 最小1 ...

  6. 标签传播算法(Label Propagation Algorithm, LPA)初探

    0. 社区划分简介 0x1:非重叠社区划分方法 在一个网络里面,每一个样本只能是属于一个社区的,那么这样的问题就称为非重叠社区划分. 在非重叠社区划分算法里面,有很多的方法: 1. 基于模块度优化的社 ...

  7. 【决战西二旗】|理解Sort算法

    前言 前面两篇文章介绍了快速排序的基础知识和优化方向,今天来看一下STL中的sort算法的底层实现和代码技巧. 众所周知STL是借助于模板化来支撑数据结构和算法的通用化,通用化对于C++使用者来说已经 ...

  8. K-近邻算法kNN

    K-近邻算法(k-Nearest Neighbor,简称kNN)采用测量不同特征值之间的距离方法进行分类,是一种常用的监督学习方法,其工作机制很简单:给定测试样本,基于某种距离亮度找出训练集中与其靠近 ...

  9. c++模板库(简介)

    目 录 STL 简介 ......................................................................................... ...

随机推荐

  1. java编程思想

    Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而且在大型项目开发中也是常用的知识,既有简单的概念理 ...

  2. 关于byte[]字节传输的大端和小端小议

    当前的存储器,多以byte为访问的最小单元,当一个逻辑上的地址必须分割为物理上的若干单元时就存在了先放谁后放谁的问题,于是端(endian)的问题应运而生了,对于不同的存储方法,就有大端(big-en ...

  3. 149. Max Points on a Line *HARD* 求点集中在一条直线上的最多点数

    Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...

  4. R-Studio

    R-Studio是一个功能强大.节省成本的反删除和数据恢复软件系列.它采用独特的数据恢复新技术,为恢复FAT12/16/32.NTFS.NTFS5(由 Windows 2000/XP/2003/Vis ...

  5. [整理]Svn常见问题汇总。

    1.’.’ is not a working copy.Can’t open file‘.svn/entries’: 系统找不到指定的路径. 解答:原因是输入的访问路径不正确,如svn://192.1 ...

  6. xml数据解析调研

    XML数据解析http://www.tuicool.com/articles/Nraau2(必用) http://www.cnblogs.com/pengyingh/articles/2342699. ...

  7. PHPExcel 学习笔记

    首先到phpexcel官网上下载最新的phpexcel类,下周解压缩一个classes文件夹,里面包含了PHPExcel.php和PHPExcel的文件夹,这个类文件和文件夹是我们需要的,把class ...

  8. wp8.1 Study13:在WP8.1中分享文件和数据

    绪论:不同于windows, 在wp8.1中,如果不止一个程序可以接受其Uri或者文件,shell会提供一个界面让用户选择用哪个程序.而在windows中,用户可以在设置那里设置各种文件和Uri的默认 ...

  9. IE9的css hack

    以前写过<IE8的css hack>,ie9一出css hack也该更新,以前一直没关注,今天在内部参考群mxclion分享了IE9的css hack,拿出来也分享一下: select { ...

  10. 展辰涂料如何利用K2BPM加强流程管控?

    展辰涂料集团股份有限公司是一家集环保涂料研发.生产.销售和工程施工为一体的国家级高新技术企业.展辰涂料集团股份有限公司是我国最大的民族涂料企业之一,自成立以来就高度注重产品技术研发,截至目前,公司已取 ...