问题
怎么在40亿个整数中找到唯一重复的数字?
1.Set的不可重复性
if(set.contains(x))
System.out.println("重复的数字是"+x);
else{
set.add(x);
}
但是,contains()方法消耗的时间,消耗的空间很大,毕竟有约40亿的数据,所以觉得HashSet是不可取的。
2.位图
BitSet就是位图,它的值只有1和0。内部是基于long[]实现的,long是8字节(64位),所以Bitset最小是64位,每次扩大一次扩大64位,即内部大小是64的倍数。每次BitSet新增加一个数字时,就将该位置为1。
也就是说BitSet并不直接存储每个数据,而是存储数字是否存在过(1表示存在,0表示不存在)。
数字范围 | [0,63] | [64,127] | [128,191] | … |
---|---|---|---|---|
long数组索引 | 0 | 1 | 2 | … |
若添加一个数字 10 ,那么将long[0]的二进制位中从左往右第十个数置为1,
若添加一个数字 64 ,那么将long[1]的二进制位中从左往右第一个数置为1,没有添加的数字所在位数是0,用此方法就可记录一个数字是否在BitSet中。
牛客题目
凡是涉及到去重统计都可以用位图实现。因为每一个不同的数据只需要用二进制的一位存储即可,大大减小了统计所使用的存储空
import java.util.Scanner;
import java.util.BitSet;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String line = scanner.next();
//总共有128个字符。字需要用128位
BitSet bitSet = new BitSet(128);
for (char c : line.toCharArray()) {
//判断字符c是否已出现
if (!bitSet.get(c)) {
//未出现就设置为已出现
bitSet.set(c);
}
}
//统计有多少字符已出现过
System.out.println(bitSet.cardinality());
}
}
参考:Java BitSet解决海量数据去重