該算法是O(1)空間(有一些作弊行爲),O(n)的時間(平均),需要將光源陣列是非const並在結束破壞它。它也限制了數組中的可能值(每個值的三位應該爲算法保留)。
答案的一半已經在問題中。使用hashmap。如果一個數字被擊中兩次,使用索引差異,更新迄今爲止最好的結果,並將該數字從哈希映射中移除以釋放空間。爲了使其成爲O(1)空間,只需重新使用源數組。將數組轉換爲散列映射。
將數組元素轉換爲散列表單元格之前,請記住它的值和位置。之後它可能會被安全覆蓋。然後使用這個值來計算hashmap中的新位置並覆蓋它。元素被這樣洗牌,直到找到一個空單元。要繼續,請選擇任何尚未重新排序的元素。當一切都重新排序後,每個int對肯定會被擊兩次,這裏我們有一個空的hashmap和一個更新的最佳結果值。
一個保留位用於將數組元素轉換爲散列映射單元。在開始時它被清除。當一個值被重新排序到哈希映射單元格時,該位被設置。如果該位未被設置爲被覆蓋的元素,則該元素僅被接着處理。如果此位設置爲要覆蓋的元素,則會出現衝突,請選取第一個未使用的元素(此位未設置)並覆蓋它。
2個更多的保留位用於鏈接衝突的值。他們對連鎖開始/結束/繼續的位置進行編碼。 (有可能優化此算法,以便只需要2個保留位...)
散列表單元格應包含這3個保留位,原始值索引和一些信息以唯一標識此元素。爲了使這成爲可能,散列函數應該是可逆的,以便部分值可以根據其在表格中的位置被恢復。在最簡單的情況下,散列函數只是ceil(log(n))
最低有效位。在表中的值由3個字段:
3
保留位從原來的值
32 - 3 - (ceil(log(n)))
高階位爲原始陣列
時間複雜度在元件的位置
ceil(log(n))
位僅爲平均值O(n);最壞情況下的複雜度是O(n^2)。 該算法的其他變體是將數組順序轉換爲散列映射:在每個步驟m
具有2^m
數組的第一個元素轉換爲散列映射。當m
較低時,某些恆定大小的陣列可能會與散列圖交錯以提高性能。當m
很高時,應該有足夠的int對,它們已經被處理,並且不再需要空間。
我認爲,你可以明顯地使它更快......只是一個提示 - 在你的例子中,在你發現`a [0]`距離是`5`後,你不需要檢查更多的值根本來說,因爲數組的大小是'6'。 – lapk 2011-12-16 07:30:17
@AzzA這可以確保速度,但它不會影響線性漸近增長率。 – 2011-12-16 07:40:52
這是面試問題嗎? – 2011-12-16 09:18:17