我的位向量有什么问题?

时间:2012-11-25 16:58:57

标签: java algorithm bit-manipulation bit bitvector

我正在尝试创建一个由int[]支持的位向量 所以我有以下代码:

public class BitVector {  

  int[] vector = new int[1 << 16];  

  public void setBit(int nextInt) {  
    nextInt = nextInt & 0xFFFF;  
    int pos = nextInt / 32;  
    int offset = nextInt % 32;  
    vector[pos] |= (1 << offset);    
  }

  public int findClearedBit() {  

    for(int i = 0;  i < vector.length; i++){              
            for(int j = 0; j < 8; j++){  
                if((vector[i] & (1 << j)) == 0)   
            return i * 32 +  j;  
        }  
    }  

    return -1;  
   }  

}  

我知道也许我应该使用byte[]代替等等但是我想知道为什么这样做不起作用。
我的想法是从流中传入int并保留低16位并将相应位标记为设置。因此,当我迭代向量时,我会发现缺少数字(用低16位表示) 但我得错了结果。所以我相信我的处理是错误的 有什么想法吗?

更新
我有一个32位整数流。当我读到它时,我尝试用使用较低的16位标记缺少的数字并设置位向量(已发布的代码)。
我还试图找到第二次读取流的上部16位丢失 因此,缺少的数字是:231719592 =(1101110011111100001010101000)=(3535 - 49832) 当我读取流时,我不会将49832作为缺少的低位而是65536

更新2:

public int findMissingInt(File f)throws Exception{  
    Scanner sc = new Scanner(f);  
    int SIZE = 1 << 16; 
    int[] occurences = new int[SIZE];  
    while(sc.hasNext()){  
    occurences[getIdx(sc.nextInt())]++;  
    }  

    int missingUpper = -1;  
    for(int i = 0; i < occurences.length; i++){  
    if(occurences[i] < SIZE){  
        System.out.println("Found upper bits:"+i);  
        missingUpper = i;  
        break;  
    }  
    }
    if(missingUpper == -1){   
    return -1;  
    }  
    //Arrays.fill(occurences, 0);  //I reused this. Bellow changed after answer of Peter de Rivaz 
    BitVector v = new BitVector(new int[1 << (16-5)]);  
    sc = new Scanner(f);
    while(sc.hasNext()){  
    v.setBit(sc.nextInt());  
    }  

    int missingLower = v.findClearedBit();
    System.out.println("Lower bits:"+missingLower);   
    return createNumber(missingUpper, missingLower);  

}   


private int createNumber(int missingUpper, int missingLower) {  
        int result = missingUpper;  
        result = result << 16;  

        return result | missingLower;  
}  



public int getIdx(int nextInt) {          
    return (nextInt >>> 16);        
}    

我明白了:

Missing number=231719592  
Found upper bits:3535 //CORRECT  
Lower bits:-1  //WRONG
Actual missing number=-1  //WRONG

1 个答案:

答案 0 :(得分:5)

我认为有两个问题:

  1. 您的阵列有65536个条目,但每个条目中存储32位,因此您只需要65536/32个条目。

  2. 在每个int中存储32位,但在查找间隙时只检查j从0到7

  3. 第一个错误意味着您的程序将65536报告为丢失的16位数字。 第二个错误意味着您的程序没有发现丢失的数字。

    即。变化

    int[] vector = new int[1 << 16];
    

    int[] vector = new int[1 << (16-5)];
    

    并更改

    for(int j = 0; j < 8; j++)
    

    for(int j = 0; j < 32; j++)
    

    修改

    从评论来看,问题实际上是如何在RAM有限的情况下找到缺失的数字。可以找到这个问题的答案here on stackoverflow

    更高级代码中还有一个错误。

    在填充bitset的第二次传递期间,您应该只包含具有匹配的高位的数字。

    即。变化

    v.setBit(sc.nextInt());
    

    类似

    int nx = sc.nextInt();
    if (getIdx(nx)==missingUpper)
      v.setBit(nx);