[英]Why is using sorting (O(n log n) complexity) to find the majority element faster than using a HashMap (O(n) complexity)?
多數元素問題:
給定一個大小為 n 的數組,找到多數元素。 多數元素是出現超過⌊ n/2 ⌋次的元素。 您可以假設數組是非空的,並且多數元素始終存在於數組中。
// Solution1 - Sorting ----------------------------------------------------------------
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
}
// Solution2 - HashMap ---------------------------------------------------------------
class Solution {
public int majorityElement(int[] nums) {
// int[] arr1 = new int[nums.length];
HashMap<Integer, Integer> map = new HashMap<>(100);
Integer k = new Integer(-1);
try{
for(int i : nums){
if(map.containsKey(i)){
map.put(i, map.get(i)+1);
}
else{
map.put(i, 1);
}
}
for(Map.Entry<Integer, Integer> entry : map.entrySet()){
if(entry.getValue()>(nums.length/2)){
k = entry.getKey();
break;
}
}
}catch(Exception e){
throw new IllegalArgumentException("Error");
}
return k;
}
}
Arrays.sort() function 在 Java 中使用 QuickSort 實現,時間復雜度為O(n log n) 。
另一方面,使用 HashMap 找到多數元素只有O(n)時間復雜度。
因此,解決方案 1(排序)應該比解決方案 2 (HashMap)花費更長的時間,但是當我在 LeetCode 上做這個問題時,解決方案 2 所花費的平均時間比解決方案 1 多得多(幾乎是 8 倍)。
為什么會這樣? 我真的很困惑......
測試用例的大小是原因嗎? 當測試用例中的元素數量急劇增加時,解決方案 2 會變得更有效率嗎?
Big O 並不是衡量實際表現的標准。 它只會讓您了解與 n 相比您的表現將如何發展。
實際上,對於某些 n,O(n.logn) 中的算法最終會比 O(n) 慢。 但是那個 n 可能是 1、10、10^6 甚至 10^600——此時它可能無關緊要,因為你永遠不會遇到這樣的數據集——或者你沒有足夠的硬件來處理它。
軟件工程師必須同時考慮實際性能和實際極限下的性能。 例如 hash map 查找在理論上比未排序的數組查找更快......但是大多數 arrays 都很小(由於額外的代碼復雜性,10-100 個元素的優勢)。
您當然可以稍微優化您的代碼,但在這種情況下,您不太可能更改小 n 的結果,除非您引入另一個因素(例如,用常數人為地減慢每個周期的時間)。
(本來想找個很好的比喻來說明,但是比想象的要難……)
這取決於測試用例,有些測試用例在 HashMap 中會更快,而另一些則不然。
這是為什么? 最壞情況下的解決方案 1受讓人O(N log 2 N) ,但 HashMap O(N. (M + R))其中 M 是沖突成本, R 是調整陣列大小的成本。
HashMap 內部使用了一個名為table
的數組,當輸入增加或縮小時,它會調整不同的時間。 您為其分配的初始容量為 100。
那么讓我們看看會發生什么? Java 使用單獨的鏈接來解決沖突,並且某些測試用例可能有很多沖突,這導致查詢或更新 hashmap 時會花費大量時間。
結論hashmap 的實現受兩個因素影響: 1. 根據輸入大小調整表數組大小 2. 輸入中出現了多少沖突
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.