騰訊面試題:給20億個不重複的unsigned int的整數,沒排過序的,然後再給一個數,如何快速判斷這個數是否在那40億個數當中並且所耗內存儘可能的少?
解析:bitmap算法就好辦多了
所謂bitmap,就是用每一位來存放某種狀態,適用於大規模數據,但數據狀態又不是很多的情況。通常是用來判斷某個數據存不存在的。
一,申請512M的內存
一個bit位代表一個unsigned int值
讀入20億個數,設置相應的bit位
讀入要查詢的數,查看相應bit位是否爲1,爲1表示存在,爲0表示不存在
二、使用位圖法判斷整形數組是否存在重複
判斷集合中存在重複是常見編程任務之一,當集合中數據量比較大時我們通常希望少進行幾次掃描,這時雙重循環法就不可取了。
java 代碼實現
import java.util.BitSet;
/**
* 大數據處理算法一,bitmap算法
* @author JYC506
*
*/
public class BitMap {
byte[] tem;
public BitMap(int length) {
this.tem = new byte[length];
}
public void add(int num) {
if (num < tem.length) {
if (tem[num] != 1) {
tem[num] = 1;
}
}
}
public boolean contain(int num) {
if (num < tem.length) {
if (tem[num] == 1) {
return true;
}
}
return false;
}
public static void main(String[] args) {
/*運行前內存*/
long beforeMemory = Runtime.getRuntime().totalMemory();
long start1=System.currentTimeMillis();
BitSet set = new BitSet(2000000000);
for (int i = 0; i < 2000000000; i++) {
/*假設898989這個數不在20億個數裏面*/
if (i != 898989) {
set.set(i, true);
}
}
/*創建20億個數後所佔內存*/
long afterMemory = Runtime.getRuntime().totalMemory();
long end1=System.currentTimeMillis();
System.out.println("總共內存使用:" + (afterMemory - beforeMemory) / 1024 / 1024 + "MB");
System.out.println("存入內存耗時:"+(end1-start1)+"毫秒");
long start2 = System.currentTimeMillis();
boolean isExit1=set.get(898989);
boolean isExit2=set.get(900000);
long end2 = System.currentTimeMillis();
/*輸出在20億個數中判斷898989是否包含在裏面*/
System.out.println(isExit1);
System.out.println("20個億中"+(isExit1?"包含":"不包含")+898989);
System.out.println("20個億中"+(isExit2?"包含":"不包含")+900000);
System.out.println("查詢用時:"+(end2 - start2)+"毫秒");
}
}
運行結果