題目描述
在 2.5 億個整數中找出不重複的整數。注意:內存不足以容納這 2.5 億個整數。
解答思路
方法一:分治法
與前面的題目方法類似,先將 2.5 億個數劃分到多個小文件,用 HashSet/HashMap 找出每個小文件中不重複的整數,再合併每個子結果,即爲最終結果。
方法二:位圖法
位圖,就是用一個或多個 bit 來標記某個元素對應的值,而鍵就是該元素。採用位作爲單位來存儲數據,可以大大節省存儲空間。
位圖通過使用位數組來表示某些元素是否存在。它可以用於快速查找,判重,排序等。不是很清楚?我先舉個小例子。
假設我們要對 [0,7]
中的 5 個元素 (6, 4, 2, 1, 5) 進行排序,可以採用位圖法。0~7 範圍總共有 8 個數,只需要 8bit,即 1 個字節。首先將每個位都置 0:
0 0 0 0 0 0 0 0
然後遍歷 5 個元素,首先遇到 6,那麼將下標爲 6 的位的 0 置爲 1;接着遇到 4,把下標爲 4 的位 的 0 置爲 1:
0 0 0 0 1 0 1 0
依次遍歷,結束後,位數組是這樣的:
0 1 1 0 1 1 1 0
每個爲 1 的位,它的下標都表示了一個數:
for i in range(8):
if bits[i] == 1:
print(i)
這樣我們其實就已經實現了排序。
對於整數相關的算法的求解,位圖法是一種非常實用的算法。
那麼對於這道題,我們用 2 個 bit 來表示各個數字的狀態:
- 00 表示這個數字沒出現過;
- 01 表示這個數字出現過一次(即爲題目所找的不重複整數);
- 10 表示這個數字出現了多次。
假設有 232 個整數,總共所需內存爲 232*2b=1GB。因此,當可用內存超過 1GB 時,可以採用位圖法來判斷 232 (42.9億左右)個整數。假設內存滿足位圖法需求,進行下面的操作:
遍歷 2.5 億個整數,查看位圖中對應的位,如果是 00,則變爲 01,如果是 01 則變爲 10,如果是 10 則保持不變。遍歷結束後,查看位圖,把對應位是 01 的整數輸出即可。
方法總結
判斷數字是否重複的問題,位圖法是一種非常高效的方法。