文章目录
1 位图
位图的功能:如果一个数字大小是确定的,可以使用一个数字集合收集数字,告知这个数字是否存在(位 1 存在,位 0 不存在)。
位图的好处:极大的压缩空间
位图的实现:
public class Code01_BitMap1 {
public static class BitMap {
long[] bits;
public BitMap(int max) {
// 0 需要 1 个
// 64 需要 2 个
bits = new long[(max + 64) >> 6];
}
public void add(int num) {
// num >> 6 = num / 64 数组第几个
// num & 63 = num % 64 long 的第几位
bits[num >> 6] |= (1L << (num & 63));
}
public void remove(int num) {
// 第 num / 64 个数的 num % 64 位置 0
bits[num >> 6] &= ~(1L << (num & 63));
}
public boolean contains(int num){
return (bits[num >> 6] & (1L << (num & 63))) != 0;
}
}
public static void main(String[] args) {
System.out.println("位图测试开始!");
int max = 10000;
BitMap bitMap = new BitMap(max);
HashSet<Integer> set = new HashSet<>();
int testTime = 10000000;
for (int i = 0; i < testTime; i++) {
double rate = Math.random();
int num = (int) (Math.random() * (max + 1));
if (rate < 0.33) {
bitMap.add(num);
set.add(num);
} else if (rate < 0.66) {
bitMap.remove(num);
set.remove(num);
} else {
if (bitMap.contains(num) != set.contains(num)) {
System.out.println("Oops!");
break;
}
}
}
for (int num = 0; num <= max; num++) {
if (bitMap.contains(num) != set.contains(num)) {
System.out.println("Oops!");
break;
}
}
System.out.println("位图测试结束!");
}
}
2 位运算实现加减乘除
ublic class Code03_BitAddMinusMultiDiv {
/**
* 位运算实现加法
* a + b = 无进位相加 + 进位信息 = (a ^ b) + ((a & b) << 1).
*/
public static int add(int a, int b) {
int sum = a;
// 进位相加信息为 0 结束
while (b != 0) {
// 无进位相加值
sum = a ^ b;
// 进位信息
b = (a & b) << 1;
// 使用进位相加信息作为新的 a
a = sum;
}
return sum;
}
/**
* 位运算实现减法
* a - b = a + (-b) = a + (~b + 1).
*/
public static int minus(int a, int b) {
return add(a, add(~b, 1));
}
/**
* 位运算实现乘法
*/
public static int multi(int a, int b) {
int ans = 0;
while (b != 0) {
// 第 0 位是 1
if ((b & 1) != 0) {
ans = add(ans, a);
}
// a 向右移一位
a <<= 1;
// b 向左无符号移动一位
b >>>= 1;
}
return ans;
}
public static int negNum(int a) {
return add(~a, 1);
}
/**
* 是否负数.
*/
public static boolean isNeg(int a) {
return a < 0;
}
/**
* 位运算实现除法.
*/
public static int div(int a, int b) {
int x = isNeg(a) ? negNum(a) : a;
int y = isNeg(b) ? negNum(b) : b;
int ans = 0;
// ans = x / y;
for (int i = 30; i >= 0; i = minus(i, 1)) {
if ((x >> i) >= y) {
// 说明 ans 的第 i 位是 1
ans |= (1 << i);
x = minus(x, y << i);
}
}
// 是否符号相同
return isNeg(a) ^ isNeg(b) ? negNum(ans) : ans;
}
public static int divide(int dividend, int divisor) {
if (dividend == Integer.MIN_VALUE && divisor == Integer.MIN_VALUE) {
return 1;
} else if (divisor == Integer.MIN_VALUE) {
return 0;
} else if (dividend == Integer.MIN_VALUE) {
if (divisor == negNum(1)) {
// 如果 b == -1
return Integer.MAX_VALUE;
} else {
// c = (a + 1) / b
// e = (a - c * b) / b
// ans = c + e
int c = div(add(dividend, 1), divisor);
int e = div(minus(dividend, multi(c, divisor)), divisor);
return add(c, e);
}
} else {
return div(dividend, divisor);
}
}
public static void main(String[] args) {
System.out.println(add(5, 4));
System.out.println(minus(5, 4));
System.out.println(multi(5, 4));
System.out.println(divide(15, 3));
}
}