[英]Why are these loop & hashing operations take O(N) time complexity?
給定數組:
int arr[]= {1, 2, 3, 2, 3, 1, 3}
你被要求在數組中找到一個出現奇數次的數字。 它是 3(發生 3 次)。 時間復雜度至少應為 O(n)。 解決方案是使用HashMap
。 元素成為鍵,它們的計數成為 hashmap 的值。
// Code belongs to geeksforgeeks.org
// function to find the element occurring odd
// number of times
static int getOddOccurrence(int arr[], int n)
{
HashMap<Integer,Integer> hmap = new HashMap<>();
// Putting all elements into the HashMap
for(int i = 0; i < n; i++)
{
if(hmap.containsKey(arr[i]))
{
int val = hmap.get(arr[i]);
// If array element is already present then
// increase the count of that element.
hmap.put(arr[i], val + 1);
}
else
// if array element is not present then put
// element into the HashMap and initialize
// the count to one.
hmap.put(arr[i], 1);
}
// Checking for odd occurrence of each element present
// in the HashMap
for(Integer a:hmap.keySet())
{
if(hmap.get(a) % 2 != 0)
return a;
}
return -1;
}
我不明白為什么這個整體操作需要O(N)時間復雜度。 如果我考慮一下,僅循環就需要O(N)時間復雜度。 那些hmap.put
(插入操作)和hmap.get
(查找操作)需要O(N)並且它們嵌套在循環中。 所以通常我會認為這個 function 需要O(N^2)次。 為什么它需要O(N) ?
該算法首先迭代大小為n
的數字數組,以生成具有出現次數的 map。 應該清楚為什么這是一個O(n)
操作。 然后,在構建 hashmap 之后,它會迭代 map 並找到所有計數為奇數的條目。 這個 map 的大小實際上介於 1(在所有輸入數字相同的情況下)和n
(在所有輸入不同的情況下)之間。 因此,第二個操作也以O(n)
為界,留下整個算法O(n)
。
我不明白為什么這個整體操作需要 O(N) 時間復雜度。
您必須檢查數組的所有元素 - O(N)
對於您調用的數組的每個元素contain
、 get
和put
數組。 這些是O(1)
操作。 或者更准確地說,它們在HashMap
的生命周期內平均攤銷為O(1)
。 這是因為當數組大小與元素數量的比率超過負載因子時, HashMap
將增長其 hash 數組。
2 次或 3 次 O(1) 次操作的 O(N) 次重復是 O(N)。 量子點
參考:
嚴格來說,有幾種情況HashMap
不是O(1)
。
如果 hash function 較差(或密鑰分布是病態的),則 hash 鏈將不平衡。 對於早期HashMap
實現,這可能會導致(最壞情況) O(N)
操作,因為像get
這樣的操作必須搜索長 hash 鏈。 在最近的實現中, HashMap
將為任何太長的 hash 鏈構建平衡二叉樹。 這會導致最壞情況的O(logN)
操作。
HashMap
無法將 hash 陣列擴展到 2^31 個 hash 存儲桶之外。 因此,此時HashMap
復雜度開始轉變為O(log N)
復雜度。 但是,如果您有這么大的 map,其他次要效果可能無論如何都會影響實際性能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.