簡體   English   中英

為什么使用排序(O(n log n) 復雜度)比使用 HashMap(O(n) 復雜度)更快地找到多數元素?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM