簡體   English   中英

這種情況下bitset的空間復雜度是多少

[英]What is the space complexity of bitset in this scenario

我正在做一個 leetcode 問題,我必須找到一個大小為 [1-N] 的數組的副本,並找到了這個解決方案:

    public int findDuplicate(int[] nums) {
        BitSet bit = new BitSet();
        for(int num : nums) {
            if(!bit.get(num)) {
                bit.set(num);
            } else {
                return num;
            }
        }
        return -1;
    }

我假設在這里使用 bitset 類似於使用 boolean[] 來跟蹤我們之前看到的當前數字。 所以我的問題是空間復雜度是多少? 運行時似乎是 O(n),其中 n 是輸入數組的大小。 空間復雜度也是如此嗎?

問題鏈接: https://leetcode.com/problems/find-the-duplicate-number/

您的Bitset創建一個底層long[]來存儲值。 閱讀Bitset#set的代碼,我可以肯定地說數組永遠不會大於max(nums) / 64 * 2 = max(nums) / 32 由於long具有固定大小,因此歸結為O(max(nums)) 如果nums包含較大的值,您可以使用 hash map 做得更好。

我正在用簡單的代碼嘗試這個,它似乎證實了我對代碼的閱讀。

BitSet bitSet = new BitSet();

bitSet.set(100);
System.out.println(bitSet.toLongArray().length); // 2 (max(nums) / 32 = 3.125)

bitSet.set(64000);
System.out.println(bitSet.toLongArray().length); // 1001 (max(nums) / 32 = 2000)

bitSet.set(100_000);
System.out.println(bitSet.toLongArray().length); // 1563 (max(nums) / 32 = 3125)

請注意,我添加的2因子是保守的,通常它會是一個較小的因子,這就是為什么我的公式始終高估長數組的實際長度,但絕不會超過 2 的因子。這是代碼Bitset我添加它的位集:

private void ensureCapacity(int wordsRequired) {
    if (words.length < wordsRequired) {
        // Allocate larger of doubled size or required size
        int request = Math.max(2 * words.length, wordsRequired);
        words = Arrays.copyOf(words, request);
        sizeIsSticky = false;
    }
}

總之,如果您有理由相信您的值小於您的值(計數),我會說位設置只是一個好主意。 例如,如果您只有兩個值,但它們的值超過十億,您將不必要地分配一個包含幾百萬個元素的數組。

此外,即使在值仍然很小的情況下,此解決方案對於已排序的 arrays 的性能也很差,因為Bitset#set將始終重新分配和復制數組,因此您的復雜性根本不是線性的,它是max(nums)的二次方,這可能很糟糕如果max(nums)非常大。 要線性,您需要首先找到最大值,在Bitset中分配必要的長度,然后通過數組僅分配 go。

此時,使用 map 更簡單,適用於所有情況。 如果速度真的很重要,我敢打賭Bitset將在特定條件下擊敗 map(很多值,但很小,並且通過按所述預先調整位集的大小)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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