问题描述:
输入的是一个文件,至多包含n个正整数,每个正整数都要小于n,这里n=10^7.
每个正整数都不一样。
大概只有1MB的可用内存。
解析:如果不考虑内存大小限制的话我们可以采用,归并排序。
现在考虑1MB内存大小的限制,应该考虑这1000000个数如何存储占用较小的内存空间。
位图数据结构:代表了有限域中的稠集(dense set),每个元素至多出现一次,没有其他的数据和元素相关联。
但是即使不满足这些条件(例如:
存在多个元素或额外数据时,也可以通过使用有限域的键作为表索引,从而起到关联或对应关系。
现在我们考虑位向量,例如我们可以使用一个20位的字符串来表示一个小型的小于20的非负整数集合。比如将一个集合{1,2,3,5,8,13}存储在下面的字符串中:
0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0
集合中代表数字的各个位设置为1,而其他的位全部都设置为0.
那么N个数只需要1+N/32 的int类型存储空间 ,对于此题,大概需要1.25MB的空间。已经可以到达很可以接受的范围了。
我们只需要三个函数:清零,设置,测试。接下来就要明白清楚如何进行位操作。
#define BITSPERWORD 32
#define SHIFT 5
#define MASK 0x1f
#define N 10000000
int a[1+N/BITSPERWORD];
void set(int i)
{
a[i>>SHIFT] |= (1<<(i&MASK));
}
void clear(int i)
{
a[i>>SHIFT] &= ~(1<<(i&MASK));
}
int test(int i)
{
return a[i>>SHIFT] & (1<<(i&MASK));
}
注释:
i>>SHIFT 相当于 i/32得到对应数组下标;
i&MASK相当于 i mod 32,得到应该设置在哪位;
1<<(i&MASK) 左移i&MASK位,取得相应的掩码。
原文链接:http://hi.baidu.com/liaopeter2009/blog/item/84d431df7a0a4d385882dd31.html