编程珠玑第一章补充

2、求出2.5亿个整数中不重复的数字,注意内存无法存下2.5亿的数字。

(1)说明你的思路

(2)写出你的算法,可以用语言实现或者用伪代码表示

 

个人提示:位图法

1、这里用到两个位图,先填充第一个位图a。当发现一个数字被填充过之后,则用这个数字填充b。很明显,b中记录的是重复出现过的数字。

2、当扫描完一次之后。再扫描b位图。只要出现在b位图中的数,就拿去清除a位图中的位。最后a中的数字保证是只出现一次的。

3、最后把a位图中记录的数输出。


值得注意的是:输出的数可能是负数,为了处理方便在处理时,统一转化成为无符号数,输出的时候,再转换成为负数则可。


你可以先把ms的值改小一些进行测试。由于算法针对的是2.1亿的数据量,所以常规的小数据是体现不出优势的。

当改小ms的值为100之后,你输入的值需要位于1~99之间。(如果不改MS的值,那么代码为正解)

#include <stdio.h>
#include <stdlib.h>

#define BITSPERWORD 32
#define SHIFT 5
#define MASK 0x1F

const unsigned long long ms = 4294967295;
int a[134217728];
int b[134217728];
void set(int *a, unsigned int i) {        a[i>>SHIFT] |=  (1<<(i & MASK)); }
void clr(int *b, unsigned int i) {        a[i>>SHIFT] &= ~(1<<(i & MASK)); }
int  test(int *a, unsigned int i){ return a[i>>SHIFT] &   (1<<(i & MASK)); }

int main()
{
	int n;
	unsigned int x;
	unsigned long long i;
	while (scanf("%d", &n) != EOF){
		x = n;
		if (test(a, x) == 0) set(a, x);
		else set(b, x);
	}
	for (i = 0; i < ms; ++i){
		x = i;
		if (test(b, x)) clr(a, x);
	}

	for (i = 0; i < ms; ++i){
		x = i;
		if (test(a, x)) printf("%d\n", (int)x);
	}
	return 0;
}


你可能感兴趣的:(编程珠玑第一章补充)