轉自:https://blog.csdn.net/h348592532/article/details/45362661
騰訊面試題:給20億個不重複的unsigned int的整數,沒排過序的,然後再給一個數,如何快速判斷這個數是否在那40億個數當中並且所耗內存儘可能的少?
解析:bitmap算法就好辦多了
所謂bitmap,就是用每一位來存放某種狀態,適用於大規模數據,但數據狀態又不是很多的情況。通常是用來判斷某個數據存不存在的。
例如,要判斷一千萬個人的狀態,每個人只有兩種狀態:男人,女人,可以用0,1表示。那麼就可以開一個int數組,一個int有32個位,就可以表示32個人。操作的時候可以使用位操作。
一,申請512M的內存
一個bit位代表一個unsigned int值
讀入20億個數,設置相應的bit位
讀入要查詢的數,查看相應bit位是否爲1,爲1表示存在,爲0表示不存在
二、使用位圖法判斷整形數組是否存在重複
判斷集合中存在重複是常見編程任務之一,當集合中數據量比較大時我們通常希望少進行幾次掃描,這時雙重循環法就不可取了。
位圖法比較適合於這種情況,它的做法是按照集合中最大元素max創建一個長度爲max+1的新數組,然後再次掃描原數組,遇到幾就給新數組的第幾位置上1,如遇到 5就給新數組的第六個元素置1,這樣下次再遇到5想置位時發現新數組的第六個元素已經是1了,這說明這次的數據肯定和以前的數據存在着重複。這種給新數組初始化時置零其後置一的做法類似於位圖的處理方法故稱位圖法。它的運算次數最壞的情況爲2N。如果已知數組的最大值即能事先給新數組定長的話效率還能提高一倍。
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)+"毫秒");
}
}