所谓的BitMap就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来存储数据,因此可以大大节省存储空间。
1. 基本思想
假设我们要对0-7内的5个元素(4,7,2,5,3)进行排序(这里假设元素没有重复)。我们可以使用BitMap算法达到排序目的。
7<2^3所以我们需要8个byte(这里我们使用int(32 bit)。
-
首先我们初始化一个int
-
然后便利这5个元素,第一个元素是4,因为下边从0开始,因此我们把第五个字节的值设置为1
-
然后再处理剩下的四个元素,最终前8个字节的状态如下图
这样便达到了排序的目的
从上面的例子可以看出,BitMap算法的思想还是比较简单的,关键的问题是如何确定10进制数到二进制的转换
MAP映射:
我们接着用int数组为例
a[0]-----------------------------> 0-31 bit
a[1]------------------------------> 32-63 bit
a[2]-------------------------------> 64-95 bit
a[3]--------------------------------> 96-127 bit
......................................................
那么十进制数如何转换为对应的bit位,下面介绍用位移将十进制数转换为对应的bit位:
1.求十进制数在对应数组a中的下标
因为每个int对应32个bit,所以可得下标为n/32 =》a[n/32]
2.求出十进制数在对应数a[i]中的下标
通过模32求得在对应数组a[i]中的下标,即n%32。
3.位移
对于一个十进制数n,对应在数组a[n/32][n%32]中,但数组a毕竟不是一个二维数组,我们通过移位操作实现置1
a[n/32] |= 1 << n % 32
移位操作:
a[n>>5] |= 1 << (n & 0x1F)
n & 0x1F 保留n的后五位 相当于 n % 32 求十进制数在数组a[i]中的下标
应用范围: 可以运用在快速查找、去重、排序、压缩数据等。
例题: 力扣41. 缺失的第一个正数
给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数。
示例 1:
输入: [1,2,0]
输出: 3
示例 2:
输入: [3,4,-1,1]
输出: 2
示例 3:
输入: [7,8,9,11,12]
输出: 1
提示:
你的算法的时间复杂度应为O(n),并且只能使用常数级别的额外空间。
普通解法
class Solution {
public int firstMissingPositive(int[] nums) {
int len = nums.length;
int[] vis = new int[len+2];
for( int i = 0; i < len ; i++){
if(nums[i]>=1 & len>=nums[i])
vis[nums[i]] = 1;
}
for( int i = 1; i <= len+1; i++)
if(vis[i] == 0)
return i;
return 1;
}
}
Bitmap解法