Bit-Map实现查找数组中的重复数字

Bit-Map中文翻译为位图,其实和本文所谓的Bit-Map是有出入的。

所谓的Bit-Map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素。由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省。

查找一个数组中的重复数字,假设数组时从0开始的,且数组是乱序的,不用Bit-Map的方法就是申请一个boolean数组,数组的长度等于要去重数组的长度 。然后遍历要去重的数组,得到每个数字,在boolean数组的相应索引位置判断,如果为false,则更新为true,如果为true,则这个索引位置所对应的数组是重复数字。

例如:要去重的数组为 {2, 3, 2, 1, 5, 4},初始化boolean数组 {false, false, false, false, false, false}

对数组进行遍历,第一个元素为 2 ,则boolean索引为 2 的位置进行更新操作。

更新后的beelean数组为 {false, false, true, false, false, false}

下一个元素为 3 ,索引为 3 的元素为 false,说明 3 还没有出现过,则更新为true。

更新后的boolean数组为 {false, false, true, true, false, false}

下一个元素为 2 ,索引为 2 的元素为 true,说明 2 已经出现过,则元素 2 为第一个重复的元素。

代码实现:

public boolean duplicate(int[] numbers) {
    if(numbers == null && numbers.length == 0) return false;
    boolean[] b = new boolean[numbers.length];
    for(int i = 0; i < numbers.length; i++) {
        if(b[numbers[i] == false) {
            b[numbers[i]] = true;
        } else {
            return false         //说明数组有重复元素
        }    
    }
    return true                //数组无重复元素
}

代码实现非常简单,但是有一个问题,boolean类型在java中所占的字节,可以参考:        https://blog.csdn.net/YuanMxy/article/details/74170745

从网上查阅资料了解到,boolean的大小JVM规范并没有指定。那boolean的大小就取决于JVM是如何实现的了。但是大多数实践发现,一个boolean所占大小为 1byte 。 http://blog.51cto.com/mb1069/1077652 

1byte = 8bit,虚拟机的实现可能是用 0000 0001 表示 true,用 0000 0000 表示false,有 8 个位,但是只用到了 1 个位,在如今大数据的时代下,这是非常严重的内存浪费。在内存相同的情况下,如果 8个位 全部利用起来,可能使一次处理数据的数量提升 8倍。所以我们就要考虑把另外的七个位利用起来。

Bit-Map用byte简单实现方法:

用byte数组,一个byte所占内存空间为 1字节 ,也就是 8bit,但是却可以表示8种状态。还拿上面的去重数组举例

去重数组 {2, 3, 0, 1, 3, 4},初始化一个byte,值为 0, 二进制位 0000 0000。

一个byte可以表示 0 ~ 7。对数组进行遍历,第一个元素为 2,则把第三位也就是 2 的位置置为 1。

现在byte表示有一个元素 2 。

下一个元素为 3,则把第三位置为 1。

下一个为 0 。

下一个为1 。

再下一个为 3 ,但是此时 3 的位置已经被置为 1 了,所以 3 是第一个重复的元素。

Bit-Map大致原理就是这样,本来用 6 byte 才能搞定的事情,现在用 1 byte就能搞定。

实现代码如下:

private static byte[] bitmap;

public static void initBitMap(int capacity) {
    int length = numbers.length % 8 == 0 ? numbers.length / 8 : numbers.length / 8 + 1;
    bitmap = new byte[length];    //如果numbers.length % 8 == 0,就不用 + 1

}
    
public static boolean setBit(int index) {
    int bIndex = index % 8;
    index = index / 8;
    byte b = (byte) (bitmap[index] >> bIndex);
    //以下代码有很大的改进空间,留给小伙伴们了
    if((b & 0x01) == 1) return false;
    byte temp = (byte) (0x01 << bIndex);
    bitmap[index] = (byte) (bitmap[index] | temp);
    return true;
}

public static boolean duplicate(int[] numbers) {
    if(numbers == null || numbers.length == 0) return false;
    initBitMap(numbers.length);
    for(int i = 0; i < numbers.length; ++i) {
        if(!setBit(numbers[i]) return false;
    }
    return true;
}

以上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值