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