问题:如何在2.5亿个无符号正整数中找出不重复的整数,内存不足以容纳这2.5亿个整数
解法:采用BitMap,每个整数分配2个bit
00 => 0 表示没出现过
01 => 1 表示出现过1次
10 =>2 表示出现过多次
11 =>3 表示无效数据。
每个无符号整数的取值范围为0~2^32-1,BitMap空间复杂度取决于MAX_VALUE,因此需要一个长度为2 ^ 32的BitMap,总占用空间为2^32 * 2bit = 1 GB。
使用Java程序进行实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| import java.util.*;
public class BitMapTest {
static byte[] flags = new byte[1000];
public static void main(String[] args) { int[] nums = new int[2000]; Map<Integer, Integer> map = new HashMap<>(nums.length); Random random = new Random(); System.out.println("原始数据:"); for (int i = 0; i < nums.length; i++) { int num = random.nextInt(flags.length * 4); nums[i] = num; System.out.print(num + " "); map.put(num, map.getOrDefault(num, 0) + 1); setVal(num); } System.out.println(); System.out.println("-------------------"); List<Integer> bitMapAns = new ArrayList<>(); List<Integer> hashMapAns = new ArrayList<>(); for (int i = 0; i < nums.length; i++) { if (getVal(nums[i]) == 1) { bitMapAns.add(nums[i]); } if (map.getOrDefault(nums[i], 0) == 1) { hashMapAns.add(nums[i]); } } System.out.println("只出现过一次的数据:"); System.out.println(bitMapAns); System.out.println("bitMapAns 是否和 hashMapAns相同:" + bitMapAns.equals(hashMapAns)); }
public static void setVal(int idx) { int val = getVal(idx); if (val >= 2) { return; } int pos = idx / 4; int loc = idx % 4;
int newVal = (flags[pos] & ~(3 << (loc * 2))) | ((val + 1) << (loc * 2)); flags[pos] = (byte) newVal; }
public static int getVal(int idx) { int pos = idx / 4; int loc = idx % 4;
int val = (flags[pos] >> (loc * 2)) & (byte) 3; return val; }
}
|
运行结果:
上述通过HashMap
的方案可以检验BitMap
的答案是正确的,并且成功节省了内存空间。