Hamming Weight,即汉明重量,指的是一个位数组中非0二进制位的数量。
解决问题:
有100M的二进制数据,算出里面有多少个1 ?(1MB = 1,000,000 Byte = 8,000,000 bit)
1、遍历法:
遍历 8 亿次,右移比较 8 亿次。
public int hammingWeight(int n) {
int res = 0;
while(n!=0) {
res+= (n & 0x1);
n >>>=1;
}
return res;
}
2、 查表法:(空间换时间)
key | value(值为1的数量) |
---|---|
0000 0000 | 0 |
0000 0001 | 1 |
… | … |
1111 1111 | 8 |
遍历 1 亿次
空间: 比如java的map<String,integer>
上述键长为 8 位,那么 2 ^ 8 = 256 ,
String 所需要字节(一个英文字母或者数字占1个字节): 256 * 8 = 2048 byte
Integer 所需要字节 ( 0,1,2,3,4,5,6,7,8)(一个Integer对象粗略统计 3* 4 = 12字节) 9 * 12 = 108 byte
算上map对象总共差不多2500 byte.
若键的长度持续增加,那么比如16位:
2500 * 2 ^ ( 16 / 8 ) = 2500 * 256 = 625k byte
若是 32位:
2500 * 2 ^ ( 32 / 8 ) = 2500 * ( 2 ^ 24) = 40,000 M byte = 40G
瓶颈 :
1、 内存
2、cpu缓存 :查表之后,会有部分数据打到cpu缓存里面,方便下次使用,但是表格越大,缓存不命中的情况就越高,那么缓存就会不断换入换出,影响性能
3、汉明重量 :variable-precision SWAR 算法
第一步:
计算出来的值i的二进制可以按每2个二进制位为一组进行分组,各组的十进制表示的就是该组的汉明重量。
第二步:
计算出来的值i的二进制可以按每4个二进制位为一组进行分组,各组的十进制表示的就是该组的汉明重量。
第三步:
计算出来的值i的二进制可以按每8个二进制位为一组进行分组,各组的十进制表示的就是该组的汉明重量。
第四步:
i * (0x01010101)计算出汉明重量并记录在二进制的高八位,>>24语句则通过右移运算,将汉明重量移到最低八位,最后二