【问题标题】:What's wrong with my bit vector?我的位向量有什么问题?
【发布时间】:2012-11-25 16:58:57
【问题描述】:

我正在尝试创建一个由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

【问题讨论】:

  • 你这样做是为了好玩吗?因为Java中内置了BitSet
  • @TomaszNurkiewicz:面试练习。
  • 我不太清楚您要做什么,您能否提供一些预期的示例输入/输出
  • 你的代码适合我。
  • @DanteisnotaGeek:请参阅更新的 OP

标签: java algorithm bit-manipulation bit bitvector


【解决方案1】:

我认为有两个问题:

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

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

第一个错误意味着您的程序将 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++)

编辑

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

更高级别的代码中有一个额外的错误。

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

即改变

v.setBit(sc.nextInt());

类似

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

【讨论】:

  • Your array has 65536 entries, but you store 32 bits in each entry 但我是 nextInt = nextInt &amp; 0xFFFF; 所以我每个条目得到 16 位,对吧?
  • 是的,但是你也做了 pos = nextInt / 32,所以你只能得到 11 位 pos 的选择(这是用来索引数组的东西)
  • 但这只会影响程序,因为分配的数组比需要的大,对吧?或者我在这里遗漏了什么?
  • 它使分配的数组太大,也意味着你循环了太多的 i 值,这样你的程序将总是返回 65536 而不是 -1 以防位集已填充。
  • 您在j&lt;32 上是对的。但是,如果我现在按照您的建议进行更改,我会得到 -1 作为结果
猜你喜欢
  • 2016-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-06
  • 2022-12-06
  • 2020-12-28
  • 2017-12-13
  • 2021-09-15
相关资源
最近更新 更多