问题分析

  输入:一个包含了4 300 000 000个32位整数的文件( 其中可能有重复出现的数字 )

  输出:一个在这个文件中重复出现过了的数字

  约束:无

解答思路

  第一章中,我们学习了如何用位向量进行一个空间代价很小的排序。在第一章的一些习题中,位向量的每一位代表的数就是该位的位序:位为1时表示存在这个数,0则表示不存在。本题也可以建立一个类似的位向量。但,本题的位向量又有所不同:因为要体现出重复的数据,因此一个数至少要两个位才能表示。故在这个新的位向量中,a ( 位表示的数 )和b ( 位序的关系 )不是a = b而是a * 2 = b1以及a*2 + 1 = b2 ( b1表示a对应的第一个位的位序,b2表示a对应的第二个位的位序 )。而且,位序00表示这两个位序对应的数不存在,位序01表示出现过一次,10表示出现过两次或者两次以上,看清楚包括两次及以上!

  建立好位向量后,就开始检索位向量,将所有“ 10 "位对应的数输出即可。

效率分析

  空间:4 300 000 000 * 2 ( bit ) ,也就是1GB左右的样子。

  时间:O( N ) ,N这里表示输入文件中数字的个数。

代码实现

 #include <iostream>
#include <fstream>
#include <string> using namespace std; // 每个整数的位数
#define BITSPERWORD 32
// 每次位移量
#define SHIFT 5
// 取模掩码
#define MASK 0x1F
// 位向量的元素个数
#define N 8600000000 // 模拟数组
int a[ + N/BITSPERWORD]; /*
* 函数功能:置位向量第i位为1
* 函数说明:" i>>SHIFT "等于" i/32 " 获取到位向量目标位对应的模拟数组元素的位置
" i & MASK "等于" i%32 " 获取到位向量目标位在对应的模拟数组元素中的位置
" 1<<(i & MASK) " 表示一个除了要设置的那位其他位都是0的整数
*/
void set (int i) {
a[i>>SHIFT] |= (<<(i & MASK));
} /*
* 函数功能:置位向量第i位为0
* 函数说明:" i>>SHIFT "等于" i/32 " 获取到位向量目标位对应的模拟数组元素的位置
" i & MASK "等于" i%32 " 获取到位向量目标位在对应的模拟数组元素中的位置
" 1<<(i & MASK) " 表示一个除了要清空的那位其他位都是0的整数
*/
void clr (int i) {
a[i>>SHIFT] &= ~(<<(i & MASK));
} /*
* 函数功能:获取位向量的第i位
* 函数说明:" i>>SHIFT "等于" i/32 " 获取到位向量目标位对应的模拟数组元素的位置
" i & MASK "等于" i%32 " 获取到位向量目标位在对应的模拟数组元素中的位置
" 1<<(i & MASK) " 表示一个除了要获取的那位其他位都是0的整数
*/
int tst (int i) {
return a[i>>SHIFT] & (<<(i & MASK));
} int main()
{
/*
* 清空位向量
*/
for (int i=; i < N; i++) {
clr(i);
} /*
* 打开待处理文件
*/
string filename;
cout << "输入数据文件名( 当前目录下 ):";
cin >> filename; fstream io;
io.open(filename.c_str());
if (!io) {
cout << "打开文件失败" << endl;
return ;
} /*
* 将数据导入位向量
*/
int num; while (io >> num) {
if ((tst(*num) == ) && (tst(*num + ) == )) {
set(*num+);
}
else if ((tst(*num) == ) && (tst(*num + ) != )) {
clr (*num);
clr (*num+);
set (*num);
}
} /*
* 输出结果
*/
for (int i=; i < ; i++) {
if ((tst(*i)!=) && (tst(*i + )==))
cout << i << endl;
} return ;
}

运行测试

  遗憾的是,运行出错了:

  分析了很久,程序中实在找不到问题,只得把这个问题拿去和朋友讨论。所幸某人点出了问题症结所在,令我茅塞顿开:C/C++中,数组在内存空间是连续存放的,而上述代码中的位向量数组要占用大约1GB的连续的空间,而我电脑内存本身才2G,系统分配不了这么大的连续空间给我。于是系统只得报错。另一人更犀利,他指出“ 题目不是只让你找一个重复的数吗?既然找一个就可以了,你何必用两个位来表示一个数呢?”。听到这个让我吐血。。。但,即便一位表示一数,也要用500多MB连续内存空间啊,很多机器都吃不消的。

  为了解决这个问题,我必须想到一种内存消耗更小的算法,而不是去电脑城买内存条。

  

第 2 章 第 2 题 找" 重数/漏数 "问题 位向量实现的更多相关文章

  1. 《学习OpenCV》练习题第四章第八题ab

    这道题是利用OpenCV例子程序里自带的人脸检测程序,做点图像的复制操作以及alpha融合. 说明:人脸检测的程序我参照了网上现有的例子程序,没有用我用的OpenCV版本(2.4.5)的facedet ...

  2. 《学习OpenCV》练习题第四章第三题b

    #include <highgui.h> #include <cv.h> #include "opencv_libs.h" /* *<学习OpenCV ...

  3. 《学习OpenCV》练习题第四章第三题a

    #include <highgui.h> #include <cv.h> #include "opencv_libs.h" #pragma comment ...

  4. 《学习OpenCV》练习题第四章第七题abc

    题外话:一直是打算把这本书的全部课后编程题写完的,中间断了几个月,一直忙于其他事.现在开始补上. 这道题我不清楚我理解的题意是不是正确的,这道题可以练习用OpenCV实现透视变换(可以用于矫正在3维环 ...

  5. Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流)

    Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流) Description 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从 ...

  6. Newtonsoft.Json C# Json序列化和反序列化工具的使用、类型方法大全 C# 算法题系列(二) 各位相加、整数反转、回文数、罗马数字转整数 C# 算法题系列(一) 两数之和、无重复字符的最长子串 DateTime Tips c#发送邮件,可发送多个附件 MVC图片上传详解

    Newtonsoft.Json C# Json序列化和反序列化工具的使用.类型方法大全   Newtonsoft.Json Newtonsoft.Json 是.Net平台操作Json的工具,他的介绍就 ...

  7. 用JAVA写一个函数,功能例如以下: 随意给定一组数, 找出随意数相加之后的结果为35(随意设定)的情况

    用JAVA写一个函数.功能例如以下:随意给定一组数,比如{12,60,-8,99,15,35,17,18},找出随意数相加之后的结果为35(随意设定)的情况. 能够递归算法来解: package te ...

  8. 比赛--找丢失的数--解题报告T

    找丢失的数 题目大意: There is a permutation without two numbers in it, and now you know what numbers the perm ...

  9. 通过崩溃地址找错误行数之Delphi版

    通过崩溃地址找错误行数之Delphi版2009-5-11 17:42:35 来源: 转载 作者:网络 访问:360 次 被顶:2 次 字号:[大 中 小]核心提示:什么是 MAP 文件?简单地讲, M ...

随机推荐

  1. bzoj 3544 [ONTAK2010]Creative Accounting 贪心

    Description 给定一个长度为N的数组a和M,求一个区间[l,r],使得(\sum_{i=l}^{r}{a_i}) mod M的值最大,求出这个值,注意这里的mod是数学上的mod Input ...

  2. 方格取数(hdu 1565)

    Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数 ...

  3. BQ25890 charging ic evb 使用注意事項

    Origin : 今天做了一個小實驗, 從 bq25890 spec 可以知道, enable bq25896 充電的功能,有二個條件, 1.CHG_CONFIG bit 需為1. 2.ce pin ...

  4. 用python生成二维码

    Python生成二维码,可以使用qrcode模块, github地址 我是搬运工 首先安装, 因为打算生成好再展示出来,所以用到Pillow模块 pip install qrcode pip inst ...

  5. idea http请求的插件(测试接口方便)

    http://blog.csdn.net/winter_chen001/article/details/77249029

  6. 矢量图和Word:EPS,PDF,EMF和SVG

    1.EMF和Word 在学校的时候,我思考过一个问题,论文中的插图如何保证清晰度.关键之一就是使用矢量图.参考知乎问题:如何在论文中画出漂亮的插图?.常见的矢量图包括:EPS,EMF和SVG.SVG适 ...

  7. 安装部署k8s-版本-1.13

    1.环境准备 # 统一hosts cat /etc/hosts 10.0.0.10 k8s-master 10.0.0.20 k8s-node1 10.0.0.30 k8s-node2 # 同步时间 ...

  8. luogu P2746 [USACO5.3]校园网Network of Schools

    题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作“接受学校”).注意即使 B 在 A 学校的分发列表中, A 也不一定在 B 学校的列表中. 你要写 ...

  9. springboot快速集成swagger

    今天技术总监说:小明,我们本次3.0改造,使用swagger2.0作为前后端分离的接口规范,它可以一键生成前后端的API,一劳永逸--小明:??? Spring Boot 框架是目前非常流行的微服务框 ...

  10. 关于#!/usr/bin/env python 的用法

    在linux的一些脚本里,需在开头一行指定脚本的解释程序,如: !/usr/bin/env python 再如: !/usr/bin/env perl 那么 env到底有什么用?何时用这个呢?脚本用e ...