位图数组

介绍

要判断一千万个整数中是否存在某个数,如何查找?简单的想法是创建一个一千万大小的数组,然后遍历查找,这样即耗费空间又耗费时间。所以我们可以创建位图数组。

实际上这个数组就是个普通数组byte, int, long类型都可以,只不过我们每次操作的是数组中一个元素的其中一位。如果要加入一个数字11,那么我们就设置这个位图数组的第11位1,就代表这个数存在。

比如用byte类型实现一个位图数组。由于byte类型是八位,所以我们就可以数组大小为实际需求的容量/8。如果是int类型就除以32。

所以bytes[0] 就代表了位图的[0, 7]位, byte[1] 就代表了位图的[8, 15]位, 依次...

不过由于是从零开始,所以如果要对负数进行操作时,需要加上一个offset使所有数据变成非负,方便操作。

static class MyBitMap {

    private byte[] bitmap;
    private final int bit = 8;

    public MyBitMap(int size) {
      if (size <= 0) return;
      int initSize = size / bit + 1;
      bitmap = new byte[initSize];
    }

    public void set(int number) {
      //除以8,代表这个数字在数组中的下标
      //因为我们要找这个数字在整个位图中位于哪一位,而一个数组元素是8位
      //所以除以8就能找到(它对应的位所在的byte类型数据)在数组中的位置。
      int index = number / bit;
      //number % 8 获取到在这个byte类型中,它处于哪一位
      int position = number % bit;
      //进行或运算,即把number对应的位修改为1。
      bitmap[index] |= 1 << (bit - 1 - position);
    }


    public boolean contains(int number) {
      //在查找这个数和set方法一样,先获得对应数组中的位置
      int index = number / bit;
      //再获取这个元素中对应位的位置
      int position = number % bit;
      //查看对应位是不是1
      return (bitmap[index] & (1 << (bit - 1 - position))) != 0;
    }
  }

例题1:【LC存在重复元素】

class Solution {
  static class MyBitMap {

    private int[] bitmap;
    private final int bit = 32;

    public MyBitMap(int size) {
      if (size <= 0) return;
      int initSize = size / bit + 1;
      bitmap = new int[initSize];
    }

    public void set(int number) {
      int index = number / bit;
      int position = number % bit;
      bitmap[index] |= 1 << (bit - 1 - position);
    }


    public boolean contains(int number) {
      int index = number / bit;
      int position = number % bit;
      return (bitmap[index] & (1 << (bit - 1 - position))) != 0;
    }
  }

  public boolean containsDuplicate(int[] nums) {
    MyBitMap map = new MyBitMap((int) 1e7);
    int min = Integer.MAX_VALUE;
    for (int num : nums) {
      min = Math.min(min, num);
    }
    for (int i = 0; i < nums.length; i++) {
      if (map.contains(nums[i] - min)) return true;
      map.set(nums[i] - min);
    }
    return false;
  }
}

例题2:【涉及哈希集合】

class MyHashSet {
    private final byte[] bitmap;
    private final int bit = 8;

    /**
     * Initialize your data structure here.
     */
    public MyHashSet() {
        int size = (int) 1e6;
        int initSize = size / bit + 1;
        bitmap = new byte[initSize];
    }

    public void add(int number) {
        int index = number / bit;
        int position = number % bit;
        bitmap[index] |= 1 << (bit - 1 - position);
    }

    public void remove(int number) {
        if (!contains(number)) return;
        int index = number / bit;
        int position = number % bit;
        // 该位置置零
        bitmap[index] &= ~(1 << (bit - 1 - position));
    }

    /**
     * Returns true if this set contains the specified element
     */
    public boolean contains(int number) {
        int index = number / bit;
        int position = number % bit;
        return (bitmap[index] & (1 << (bit - 1 - position))) != 0;
    }
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值