一不小心就看到位圖法,引起了我的興趣。
簡單說下位圖法(bitmap),用每一個bit來存放某個狀態(tài),常用于正整數(shù)類型中。(具體內容請自行百度)
先來個拋磚引玉吧,曾經有一個題目,據(jù)說是騰訊的前端面試題,內容大概如下:
示例一(已刪數(shù)字):
題目:
有一組數(shù)字,從1到n,假設n=10,亂序且不重復。例如[1,5,8,3,4,9,2,6,7,10],隨機刪除3個數(shù)字,請找出3個被刪除的數(shù)字。
算法:
- 以最大數(shù)字n=10來初始化位圖數(shù)組
- 循環(huán)剩余數(shù)字,把狀態(tài)位設置進位圖數(shù)組里面(復雜度N)
- 循環(huán)狀態(tài)位數(shù)組,把狀態(tài)位不為1的提取到輸出結果數(shù)組(復雜度N)
- 總復雜度2N,N∈正整數(shù)
// 隨機刪除后的數(shù)組
var arr = [1, 3, 4, 9, 2, 7, 10];
// 位圖數(shù)組,多了索引0,所以設置11個
var bitmap = Array(11);
// 輸出數(shù)組
var outputArr = [];
// 設置位圖狀態(tài)
for (var i = 0; i < arr.length; i++) {
bitmap[arr[i]] = 1;
}
// 提取已移除的數(shù)字
for (var i = 1; i < bitmap.length; i++) {
if (!bitmap[i]) {
outputArr.push(i);
}
}
// 輸出[5, 6, 8]
console.log(outputArr);
原理:
初始化的位圖數(shù)組如下:
[undefind * 11]
設置狀態(tài)位后的位圖數(shù)組(undefind當0)如下:
[0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1 ]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
不難看出,缺失的5,6,8,位圖法就是通過這種原理來設置的
另外,位圖法還支持排序
,從上得知數(shù)字也被重新排好序了
示例二(去重):
題目:
已知兩個數(shù)組[8,4,6,2,1,9]、[3,4,5,8,9,7,0],請合并去除重復數(shù)字,并找出重復過的數(shù)字。
算法:
- 找出兩個數(shù)組中最大的數(shù)字,用于構建位圖數(shù)組, max=10(此步驟不做處理)
- 把已知的第一個數(shù)組寫進位圖數(shù)組里(復雜度N)
- 把已知的第二個數(shù)組與位圖數(shù)組做比對,狀態(tài)位為1的則是已存在的數(shù)字,即重復數(shù)字,比對完后也寫進位圖數(shù)組里(復雜度N)
- 循環(huán)位圖數(shù)組,提取所有數(shù)字,即可得出合并后的數(shù)組(復雜度N)
- 總復雜度3N,N∈正整數(shù)
var arr1 = [8, 4, 6, 2, 1, 9];
var arr2 = [3, 4, 5, 8, 9, 7, 0];
var bitmap = Array(10);
// 重復的數(shù)字
var repeatArr = [];
// 合并后的數(shù)組
var concatArr = [];
// 設置位圖狀態(tài)
for (var i = 0; i < arr1.length; i++) {
bitmap[arr1[i]] = 1;
}
// 找到重復數(shù)字
for (var i = 1; i < arr2.length; i++) {
if (bitmap[arr2[i]]) {
repeatArr.push(arr2[i]);
}
// 同時設置位圖狀態(tài)
bitmap[arr2[i]] = 1;
}
// 合并后的數(shù)組
for (var i = 0; i < bitmap.length; i++) {
if (bitmap[i]) {
concatArr.push(i);
}
}
// 輸出[4, 8, 9]
console.log(repeatArr);
// 輸出[0, 1, 2, 4, 5, 6, 7, 8, 9]
console.log(concatArr);
數(shù)量級別:
位圖法能不能計算數(shù)以億計的量級,答案是“能”
一個bit狀態(tài)位表示一條數(shù)據(jù),
我們來簡單計算一下:
1B = 8bit
1KB = 1024B
1MB = 1024KB
≈ 1024 * 1024 * 8 bit
≈ 840萬 bit
也就是說,800多萬的數(shù)據(jù)才占用了1MB內存而已,剩下的就是cpu的計算了
位圖法總結
- 只能用于正整數(shù)
- 支持排序
- 支持去重
- 支持億量級別計算
至于使用場景,需要自己摸索,至少比二叉樹的實際使用場景多