前端也有算法 - 位圖法

一不小心就看到位圖法,引起了我的興趣。
簡單說下位圖法(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ù)字。

算法:
  1. 以最大數(shù)字n=10來初始化位圖數(shù)組
  2. 循環(huán)剩余數(shù)字,把狀態(tài)位設置進位圖數(shù)組里面(復雜度N)
  3. 循環(huán)狀態(tài)位數(shù)組,把狀態(tài)位不為1的提取到輸出結果數(shù)組(復雜度N)
  4. 總復雜度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ù)字。

算法:
  1. 找出兩個數(shù)組中最大的數(shù)字,用于構建位圖數(shù)組, max=10(此步驟不做處理)
  2. 把已知的第一個數(shù)組寫進位圖數(shù)組里(復雜度N)
  3. 把已知的第二個數(shù)組與位圖數(shù)組做比對,狀態(tài)位為1的則是已存在的數(shù)字,即重復數(shù)字,比對完后也寫進位圖數(shù)組里(復雜度N)
  4. 循環(huán)位圖數(shù)組,提取所有數(shù)字,即可得出合并后的數(shù)組(復雜度N)
  5. 總復雜度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的計算了

位圖法總結

  1. 只能用于正整數(shù)
  2. 支持排序
  3. 支持去重
  4. 支持億量級別計算
    至于使用場景,需要自己摸索,至少比二叉樹的實際使用場景多
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容