找到40亿的缺失数字(再次)

时间:2012-04-16 09:23:38

标签: java algorithm optimization bit-manipulation

似乎已经被问过很多次的问题即将在40亿个数字中检测到丢失的数字。
推荐的方法似乎是使用bitset(当内存约束是问题的一部分时) 一个示例帖子是:find-an-integer-not-among-four-billion-given-ones我还可以在SO中链接到更多。

我的问题如下:bitset方法似乎隐含地认为数字 -negative。作为我链接的帖子中的一个例子,Java中有这个代码片段:

int radix = 8; 
byte[] bitfield = new byte[0xffffffff/radix]; 
void F() throws FileNotFoundException{ 
    Scanner in = new Scanner(new FileReader("a.txt")); 
    while(in.hasNextInt()){ 
        int n = in.nextInt(); 
        bitfield[n/radix] |= (1 << (n%radix)); 
    } 

    for(int i = 0; i< bitfield.lenght; i++){ 
        for(int j =0; j<radix; j++){ 
            if( (bitfield[i] & (1<<j)) == 0) System.out.print(i*radix+j); 
        } 
    } 
} 

但在Java中,所有整数都是签名的。因此,发布的代码将为负数打破。此int n = in.nextInt();可以返回否定。

所以我想我的混乱是关于这种问题/练习的两个部分:
1)可以使用bitset来表示负数吗?怎么样?
2)问题的解决方案是否与某种特定的编程语言有关?例如。在C ++中,有无符号数,我想可以接受范围是非负数的假设。

有人可以帮我理解这个吗?

2 个答案:

答案 0 :(得分:4)

long n = in.nextInt() & 0xFFFFFFFFL; 
bitfield[(int) (n/radix)] |= (1 << (n%radix));

或使用

final int bits = 3; 

bitfield[(int) (n >>> bits)] |= (1 << (n & ((1 << bits) -1)));

System.out.print((int) (i*radix+j)); 

您可能会发现使用和int[]long[]比使用byte[]

稍快一些

答案 1 :(得分:3)

嗯,这是一个明显的解决方案:由于我们知道每个数字都有一个特定的范围[a,b],你可以将下边界加到所有数字上,以获得保证的正数。

现在这对任意长数都不起作用,但那通常不是问题