题目大意:移动公司需要对已经发放的所有139段的号码进行统计排序,已经发放的139号码段的文件都存放在一个文本文件中(原题是放在两个文件中),一个号码一行,现在需要将文件里的所有号码进行排序,并写入到一个新的文件中;号码可能会有很多,最多可能有一亿个不同的号码(所有的139段号码),存入文本文件中大概要占1.2G的空间;jvm最大的内存在300以内,程序要考虑程序的可执行性及效率;只能使用Java标准库,不得使用第三方工具。 
    这是个典型的大数据量的排序算法问题,首先要考虑空间问题,一下把1.2G的数据读入内存是不太可能的,就算把1一亿条数据,转都转换成int类型存储也要占接近400M的空间。当时做个题目我并没有想太多的执行效率问题,主要就考虑了空间,而且习惯性的想到合并排序,基本思想是原文件分割成若干个小文件并排序,再将排序好的小文件合并得到最后结果,算法大概如下:

1.顺序读取存放号码文件的中所有号码,并取139之后的八位转换为int类型;每读取号码数满一百万个(这个数据可配置)将已经读取的号码排序并存入新建的临时文件。 
    2.将所有生成的号码有序的临时文件合并存入结果文件。

这个算法虽然解决了空间问题,但是运行效率极低,由于IO读写操作太多,加上步骤1中的排序的算法(快速排序)本来效率就不高(对于电话排序这种特殊情况来说),导致1亿条数据排序运行3个小时才有结果。

如果和能够减少排序的时间呢?首当其冲的减少IO操作,另外如果能够有更加好排序算法也行。前天无聊再看这个题目时突然想到大三时看《编程珠玑》时上面也有个问题的需求这个这个题目差不多,记得好像使用是位向量(实际上就是一个bit数组),用电话作为index,心中大喜,找到了解决此问题的最完美方案啦:用位向量存储电话号码,一个号码占一个bit,一亿个电话号码也只需要大概12M的空间;算法大概如下: 
      1.初始化bits[capacity]; 
      2.顺序所有读入电话号码,并转换为int类型,修改位向量值:bits[phoneNum]=1; 
      3.遍历bits数组,如果bits[index]=1,转换index为电话号码输出。 
    Java中没有bit类型,一个boolean值占空间为1byte(感兴趣的可以自己写程序验证),我自己写个个用int模拟bit数组的类,代码如下:

Java代码  
  1. public class BitArray {
  2. private int[] bits = null;
  3. private int length;
  4. //用于设置或者提取int类型的数据的某一位(bit)的值时使用
  5. private final static int[] bitValue = {
  6. 0x80000000,//10000000 00000000 00000000 00000000
  7. 0x40000000,//01000000 00000000 00000000 00000000
  8. 0x20000000,//00100000 00000000 00000000 00000000
  9. 0x10000000,//00010000 00000000 00000000 00000000
  10. 0x08000000,//00001000 00000000 00000000 00000000
  11. 0x04000000,//00000100 00000000 00000000 00000000
  12. 0x02000000,//00000010 00000000 00000000 00000000
  13. 0x01000000,//00000001 00000000 00000000 00000000
  14. 0x00800000,//00000000 10000000 00000000 00000000
  15. 0x00400000,//00000000 01000000 00000000 00000000
  16. 0x00200000,//00000000 00100000 00000000 00000000
  17. 0x00100000,//00000000 00010000 00000000 00000000
  18. 0x00080000,//00000000 00001000 00000000 00000000
  19. 0x00040000,//00000000 00000100 00000000 00000000
  20. 0x00020000,//00000000 00000010 00000000 00000000
  21. 0x00010000,//00000000 00000001 00000000 00000000
  22. 0x00008000,//00000000 00000000 10000000 00000000
  23. 0x00004000,//00000000 00000000 01000000 00000000
  24. 0x00002000,//00000000 00000000 00100000 00000000
  25. 0x00001000,//00000000 00000000 00010000 00000000
  26. 0x00000800,//00000000 00000000 00001000 00000000
  27. 0x00000400,//00000000 00000000 00000100 00000000
  28. 0x00000200,//00000000 00000000 00000010 00000000
  29. 0x00000100,//00000000 00000000 00000001 00000000
  30. 0x00000080,//00000000 00000000 00000000 10000000
  31. 0x00000040,//00000000 00000000 00000000 01000000
  32. 0x00000020,//00000000 00000000 00000000 00100000
  33. 0x00000010,//00000000 00000000 00000000 00010000
  34. 0x00000008,//00000000 00000000 00000000 00001000
  35. 0x00000004,//00000000 00000000 00000000 00000100
  36. 0x00000002,//00000000 00000000 00000000 00000010
  37. 0x00000001 //00000000 00000000 00000000 00000001
  38. };
  39. public BitArray(int length) {
  40. if(length < 0){
  41. throw new IllegalArgumentException("length必须大于零!");
  42. }
  43. bits = new int[length / 32 + (length % 32 > 0 ? 1 : 0)];
  44. this.length = length;
  45. }
  46. //取index位的值
  47. public int getBit(int index){
  48. if(index <0 || index > length){
  49. throw new IllegalArgumentException("length必须大于零小于" + length);
  50. }
  51. int intData = bits[index/32];
  52. return (intData & bitValue[index%32]) >>> (32 - index%32 -1);
  53. }
  54. //设置index位的值,只能为0或者1
  55. public void setBit(int index,int value){
  56. if(index <0 || index > length){
  57. throw new IllegalArgumentException("length必须大于零小于" + length);
  58. }
  59. if(value!=1&&value!=0){
  60. throw new IllegalArgumentException("value必须为0或者1");
  61. }
  62. int intData = bits[index/32];
  63. if(value == 1){
  64. bits[index/32] = intData | bitValue[index%32];
  65. }else{
  66. bits[index/32] = intData & ~bitValue[index%32];
  67. }
  68. }
  69. public int getLength(){
  70. return length;
  71. }
  72. }

bit数组有了,剩下就是算法代码,核心代码如下:

Java代码  
  1. bitArray = new BitArray(100000000);
  2. //顺序读取所有的手机号码
  3. while((phoneNum = bufferedReader.readLine())!=null){
  4. phoneNum = phoneNum.trim().substring(3);//13573228432
  5. //取139后8位转换为int类型
  6. phoneNumAsInt = Integer.valueOf(phoneNum);
  7. //设置对应bit值为1
  8. bitArray.setBit(phoneNumAsInt, 1);
  9. }
  10. //遍历bit数组输出所有存在的号码
  11. for(int i = 0;i<sortUnit;i++){
  12. if(bitArray.getBit(i)==1){
  13. writer.write("139" + leftPad(String.valueOf(i + sortUnit*times), 8));
  14. writer.newLine();
  15. }
  16. }
  17. writer.flush();

经测试,修改后的算法排序时只需要20多M的内存,一亿条电话号码排序只要10分钟(时间主要花在IO上),看来效果还是很明显的。 
    这个算法很快,不过也有他的局限性: 
    1.只能用于整数的排序,或者可以准确映射到正整数(对象不同对应的正整数也不相同)的数据的排序。 
    2.不能处理重复的数据,重复的数据排序后只有一条(如果有这种需求可以在这个算法的基础上修改, 给出现次数大于1的数据添加个计数器 ,然后存入Map中) 
    3.对于数据量极其大的数据处理可能还是比较占用空间, 这种情况可配合多通道排序算法解决。

PS:这个算法的思想源于《编程珠玑》,有兴趣的可以读读那本书,非常不错!

来源:http://pisces-java.iteye.com/blog/766745

公司的一道考试题算法分析——大数据量整数排序相关推荐

  1. 数据蒋堂 | 这个产品能支持多大数据量?

    作者:蒋步星 来源:数据蒋堂 本文共500字,建议阅读5分钟.似乎是支持数据量越大,产品就越厉害. 经常有用户会问这个问题,你家的产品能处理多大数据量?似乎是这个值越大产品就越牛. 这个问题,其实没多 ...

  2. MySQL数据库如何解决大数据量存储问题

    FROM http://blog.csdn.net/likika2012/article/details/38816037 各位高手您们好,我最近接手公司里一个比较棘手的问题,关于如何利用MySQL存 ...

  3. 财务大数据比赛有python吗-Python 适合大数据量的处理吗?

    我很喜欢用python,用python处理数据是家常便饭,从事的工作涉及nlp,算法,推荐,数据挖掘,数据清洗,数据量级从几十k到几T不等,我来说说吧 百万级别数据是小数据,python处理起来不成问 ...

  4. python能处理多大的数据-Python 适合大数据量的处理吗?

    python 能处理数据库中百万行级的数据吗? 处理大规模数据时有那些常用的python库,他们有什么优缺点?适用范围如何? 王守崑,推荐系统,数据挖掘 需要澄清两点之后才可以比较全面的看这个问题: ...

  5. 大数据量,海量数据 处理方法总结(转)

    最近有点忙,稍微空闲下来,发篇总结贴. 大数据量的问题是很多面试笔试中经常出现的问题,比如baidu google 腾讯 这样的一些涉及到海量数据的公司经常会问到. 下面的方法是我对海量数据的处理方法 ...

  6. 大数据量及海量数据处理算法总结

    下面的方法是我对海量数据的处理方法进行了一个一般性的总结,当然这些方法可能并不能完全覆盖所有的问题,但是这样的一些方法也基本可以处理绝大多数遇到的问题.下面的一些问题基本直接来源于公司的面试笔试题目, ...

  7. 大数据量涉及算法及常见问题

    数据量的问题是很多面试笔试中经常出现的问题,比如 google.淘宝.百度. 腾讯 这样的一些涉及到海量数据的公司经常会问到. 下面的方法是我对海量数据的处理方法进行了一个一般性的总结,当然这些方法可 ...

  8. 任何抛开业务谈大数据量的sql优化都是瞎扯

    周三去某在线旅游公司面试.被问到了一个关于数据量大的优化问题.问题是:一个主外键关联表,主表有一百万数据,外键关联表有一千万的数据,要求做一个连接. 本人接触过单表数据量最大的就是将近两亿行历史数据( ...

  9. 【Python开发】Python 适合大数据量的处理吗?

    Python 适合大数据量的处理吗? python 能处理数据库中百万行级的数据吗? 处理大规模数据时有那些常用的python库,他们有什么优缺点?适用范围如何? 需要澄清两点之后才可以比较全面的看这 ...

最新文章

  1. JavaScript高级程序设计学习笔记--引用类型
  2. 正则表达式的比较JDK1.4 vs jakarta
  3. 清除DataTable中的空行记录
  4. 河南省计算机大学应用水平考试,河南省大学计算机等级考试选择题(文管二级)...
  5. OpenGL 实例化属性的实例
  6. 李宏毅机器学习(九)Multi-lingual BERT
  7. django 路径转换器
  8. 初窥R(基本说明、获取帮助、工作空间、输入输出、包)
  9. Java获取硬盘信息
  10. Django笔记:ORM模型
  11. 用python读取图像_如何用python获取图像
  12. centos6配置mysql远程访问_一次成功的MySQL升级失败教训
  13. 图像坐标系、相机坐标系和世界坐标系 相机的内、外参数矩阵
  14. 如何在ps添加箭头_PS里怎么画箭头?PS画箭头三种方法介绍
  15. Android 项目必备(二十三)-->减小 APK 大小
  16. 10个典型的大数据案例
  17. 机器学习项目 - 泰坦尼克号乘客生还率
  18. deepin20 外接显示器,标题栏美化
  19. AI、大数据时代,智能安防在智慧城市建设中的发展与应用趋势
  20. OCSNG inventory | 介绍

热门文章

  1. 使用IDEA编写Python程序,插件安装python插件,安装python SDK运行Python程序
  2. Oracle数据库表信息,序列,视图等导出,导入。(数据库备份和恢复)
  3. 7.MongoDB java CRUD
  4. eclipse项目中的.settings .project .classpath 个人见解
  5. 处理数字_10_计算某列重复最多的值
  6. excel匹配_python中实现excel的高级筛选
  7. java代码中哪些不能犯的错误_Java程序员工作中千万不能犯的3个低级错误
  8. C++中结构体、联合体、枚举的区别
  9. 前端面试——初(H)入(T)江(M)湖(L)
  10. 一种通用递归深度检测技术 - 基于栈帧内容的检测 - Golang语言描述