1.5 高速找出機器故障
題目:如果一個機器僅僅存儲一個標號為ID的記錄,如果每份數據保存2個備份,這樣就有2個機器存儲了同樣的數據。當中ID是小於10億的整數。
問題1、在某個時間。假設得到一個數據文件ID的列表。
是否可以高速的找到這個表中僅出現一次的ID?即高速找出出現問題的機器存儲的數據ID。
問題2、如果有兩臺機器死機呢?(如果同一個數據的倆個備份不會同一時候丟失。即列表中缺少的是兩個不等的ID)
擴展題、假設全部的機子都有三個備份,也就是說同一ID的機子有三臺。並且同一時候又有三臺機子死機,還能用上面的方法解決嗎?
假設有N臺備份,又同一時候有N臺機器死機呢?
~~~~~~~~~~~~~~~~切割線
問題又一次闡述:
問題1、已知一個數組,數組中僅僅有一個數據是出現一遍的,其它數據都是出現兩遍,我們要把這個數據找出來
問題2、已知一個數組,數組中有兩個不同的數據都出現一遍,其它數據都是出現兩遍,我們要把這兩個數據找出來
問題3、已知一個數組,數組丟失了三個數據,我們要把這三個數據找出來
之後能夠擴展到N個
~~~~~~~~~~~~~~~~~切割線~~~~~~~~~~~~~~~~~~~~~
問題1、已知一個數組。數組中僅僅有一個數據是出現一遍的,其它數據都是出現兩遍,我們要把這個數據找出來
方法一、使用計數排序(借助map)
思想:遍歷整個ID列表,使用Map記錄每一個ID出現的次數。之後。僅僅出現一次的ID為所求
時間復雜度O(N),空間復雜度O(N)
註:不用map。而用數組的話,空間復雜度會大於N(N表示有N個數),應該是10億(ID的最大值可能為10億)
缺點:空間復雜度太大,對已經出現過兩次的ID仍要保存,但它已經不可能是出故障的機器了
方法二、仍使用計數排序,可是對已經出現過兩次的ID不在存儲
思想:遍歷列表。對於每個ID。先檢查hash表中是否有與之同樣的ID
若有,則從Hash表中刪除該ID。
否則,將該ID增加到hash表中。
這樣,遍歷完列表後。hash
時間復雜度O(N),空間復雜度最好為O(1),最壞為O(N)
方法三、利用異或運算(推薦使用)
思想:將列表中的全部ID異或,之後得到的值即為所求ID。
利用異或運算能夠得到
X^X=0 X^Y=Z X^0=X
時間復雜度為O(N),空間復雜度為O(1)。在時間和空間上。基本已經達到最優。
缺點:前提是僅僅有一個ID出現一次。若出現多次,則不適合
方法四、利用 "不變量" (推薦使用)
思路:這裏。全部ID的和為一個不變量,對如今剩下ID求和。全部ID的和與剩下ID的和之差即為所求ID。
時間復雜度:O(N)時間,空間復雜度O(1)
總結:使用異或 和 不變量 都已經非常優化。均能在僅僅遍歷一次列表,僅僅需一個變量的條件下解決。
~~~~~~~~~~~~~~~~~切割線~~~~~~~~~~~~~~~~~~~~~
問題2、已知一個數組。數組中有兩個不同的數據都出現一遍。其它數據都是出現兩遍,我們要把這兩個數據找出來
題裏面是丟失的是兩個不同的數據,我們這裏兩種情況都考慮下
假設缺少的兩個數字不同樣。
方法:進行異或操作
思路:因為缺少的數不同。則最後異或的結果不為0。
- (1)對數組中全部的ID進行異或,結果為a
- (2)我們找到a的二進制表示中。最低一位為1的位置b
- (3)依據b位是否為1,將ID數組中的數分為兩個數組,當中一個數組中的b位為1,還有一個隊列中的b位為0。
- (註意。每一個數組中。除了那個僅僅出現一次的數外。其它數都是出現兩次的。此時就能夠在數組內使用異或操作)
- (4)然後對兩個數組。分別進行異或操作,則將得到兩個不為0的數字。即為所丟失的兩個ID。
假設缺少的兩個數字同樣
(此時數組中全部ID都是成對出現。異或值還是為0,不能使用異或實現)
方法:能夠使用不變量實現。丟失兩個,生成兩個方程,聯立求值
-
1)首先計算出初始未丟失之前,全部ID之和。
-
(2)然後計算出丟失之後的ID之和,然後(1)(2)結果進行相減操作,得到方程x+ y = a。
- (3)利用丟失前後平方和之差,來與(2)進行聯立,得到方程x * x + y * y = b。
- (4)對雙方程進行聯立,即能夠求出終於的結果。
~~~~~~~~~~~~~~~~~切割線~~~~~~~~~~~~~~~~~~~~~
問題3、已知一個數組,數組丟失了三個數據,我們要把這三個數據找出來
之後能夠擴展到N個
方法一:我們須要建立三/N個方程,求出這些都是的數
此時,當方程為N時,要求N個方程可不好求
方法二:使用計數排序 + 計數值達到A時Map不在存儲
這時。終於能夠得到這幾個數
~~~~~~~~~~~~~~~~~切割線~~~~~~~~~~~~~~~~~~~~~
相關題目
給你一副雜亂的撲克牌(不包含大小王)。隨意從當中抽出一張牌,如何用最簡單的方法來知道抽出的是1~13中的那一張?(不要求知道花色)
方法:利用不變量
事先算好全部牌的和(1+...+13) x 4 = 364
然後分別減去留下的牌點數,終於得到的就是抽出的那一張
1.5 高速找出機器故障