BitSet 解决 40亿个整数中找到那个唯一重复的数字

基本原理
BitSet是位操作的对象,值只有0或1即false和true,内部维护了一个long数组,初始只有一个long,所以BitSet最小的size是64,当随着存储的元素越来越多,BitSet内部会动态扩充,最终内部是由N个long来存储,这些针对操作都是透明的。

用1位来表示一个数据是否出现过,0为没有出现过,1表示出现过。使用用的时候既可根据某一个是否为0表示,此数是否出现过。

一个1G的空间,有 8*1024*1024*1024=8.58*10^9bit,也就是可以表示85亿个不同的数

40亿个整数中找到那个唯一重复的数字

import java.util.BitSet;
public class BitSet2 {
        public static void main(String[] args) {
            BitSet bitSet=new BitSet();
            int[] nums={1,2,3,4,5,6,1};

            for (int num : nums) {
                if(bitSet.get(num)){
                    System.out.println(num);
                    break;
                }else {
                    bitSet.set(num);
                }
            }
        }
}

源码分析:

/**
     * Sets the bit at the specified index to {@code true}.
     *
     * @param  bitIndex a bit index
     * @throws IndexOutOfBoundsException if the specified index is negative
     * @since  JDK1.0
     */
    public void set(int bitIndex) {//62
        if (bitIndex < 0)
            throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);

        int wordIndex = wordIndex(bitIndex);//wordIndex /2^6=0;0号桶
        expandTo(wordIndex);//扩容2倍

//words数组,,,1L是Long型,64位,63-0,左移62位,即010000000000....
        words[wordIndex] |= (1L << bitIndex); // Restores invariants

        checkInvariants();
    }
  /**
     * Returns the value of the bit with the specified index. The value
     * is {@code true} if the bit with the index {@code bitIndex}
     * is currently set in this {@code BitSet}; otherwise, the result
     * is {@code false}.
     *
     * @param  bitIndex   the bit index
     * @return the value of the bit with the specified index
     * @throws IndexOutOfBoundsException if the specified index is negative
     */
    public boolean get(int bitIndex) {
        if (bitIndex < 0)
            throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);

        checkInvariants();

        int wordIndex = wordIndex(bitIndex);//wordIndex =0号桶
        return (wordIndex < wordsInUse)
            && ((words[wordIndex] & (1L << bitIndex)) != 0);
    }
/**
 (wordIndex < wordsInUse)//首先位桶足够

  ((words[wordIndex] & (1L << bitIndex)) != 0);        
等价于(words[wordIndex] & (1L << bitIndex%64)) != 0

bitIndex%64即bitIndex取低6位
然后在1左移bitIndex取低6位之后的结果


如果bitIndex=1025
wordIndex =1025/2^6=16号桶
words[wordIndex]=words[16]
1L << bitIndex即1L << bitIndex%64即 bitIndex取低六位000001=1,再1L<<1,即00...10
即1025在第16号桶的第1个比特位上,,,,,63。。。。0

*/

你可能感兴趣的:(面试算法题总结)