[英]Finding a Particular Missing Array Element: O(n+k) Complexity
我必須創建一種算法,該算法返回大小為n的數組中最大的丟失元素,該數組的范圍為值1- k 。
示例:如果數組包含1,1,3,1,3,則k = 3,n = 5,返回值應為2。
如果不考慮時間復雜度,則相對簡單。 只需遍歷數組以搜索k-1,k-2,... 2,然后第一次找不到值,就返回該值(如果不存在該值,則返回-1)。 但是,這將是一個循環內部的循環,從而導致O(n * k)復雜性。
我被特別要求在結果中實現O(n + k),盡管我是算法設計的新手,但我認為這意味着我的算法不得包含任何嵌套循環。 我所學的數組排序方法都沒有最壞的線性時間,因此我無法使用它們,也看不到任何其他方法可以在所有段中將n和k分開。
我已經在這個概念上停留了幾個小時。 我並不一定要尋找一個完整的答案,但是如果有人可以指出正確的方向,甚至可以解釋在這樣的問題中我應該如何解決O(n + k)復雜性,我將不勝感激。
具有注釋的C#示例代碼:
int k = 3;
int[] data = new int[] {1, 1, 3, 1, 3};
// Step 1: collecting items presented
// O(n): we have to scan "data" array == O(n), adding item - n * O(1) == O(n)
// O(n) + n * O(1) == O(n) + O(n) == O(n) for the step 1
HashSet<int> present = new HashSet<int>(data);
// Step 2: scan 1..k items and find items missing:
// O(k) - 1..k scan + k * O(1) - checking each item
// O(k) + k * O(1) == O(k) + O(k) = O(k) for the step 2
var missing = Enumerable
.Range(1, k) // O(k) - scan
.Where(item => !present.Contains(item)) // k * O(1) == O(k)
.ToList(); // materialize
// Test
Console.Write(string.Join(" ", missing));
最后,我們執行步驟1,然后執行步驟2:
O(n) + O(k) = O(n + k)
編輯:步驟2既不是Linq也不是lambda ,但是對於循環來說不錯了 :
for (int i = 1; i <= k; ++i) // O(k) - scan
if (!present.Contains(i)) // O(1) - check
Console.WriteLine(i);
您可以使用另一個數組來存儲事件而不使用哈希集,盡管這樣會浪費一些內存,
public int maxMissingElement(final int arr[], final int max) {
boolean[] holder = new boolean[max + 1];
for (int i = 0; i < arr.length; i++) {
holder[arr[i]]=true;
}
for (int i = max - 1; i >= 0; i--) {
if (!holder[i]) {
return i;
}
}
return -1;
}
時間復雜度:O(n + k)
空間復雜度:O(k)
我想到的第一件事是保持大小為k
的哈希集。 哈希集具有在線性k時間中創建的屬性,而查找數據的時間為O(1)
時間。
這意味着您可以為每個k值創建一個帶有標志的哈希集(或字典)。 因此對於k = 3
您將得到一個集合(0 -> false, 1 -> false, 2 -> false, 3 -> false)
。
然后,您可以簡單地以線性n時間遍歷數據數組(大小為n),並且對於每個值,只需將哈希集中的相應記錄設置為true。
完成此過程后,您將得到一個哈希集,該哈希集的記錄僅針對數據集中存在的值設置為true。
最后,只需遍歷哈希集一次,並保留一個名為result
的對象。 每次您找到一個false
的值(即數據數組中不存在),便將其與result
進行比較。 如果該值大於result
,則將result
設置為該值。
在散列集的循環結束時, result
值將是數據集中最大的缺失值。
那是O(k + n)
嗎?
我們將這些時間復雜度加起來如下:
O(k) + O(n)O(1) + O(k)*O(1)
= 2 * O(k) + O(n) = O(k) + O(n)
= O(k + n).
對我來說,保持哈希值聽起來很實用,但並不十分優雅。 我敢肯定,有一種方法可以在沒有哈希集的情況下做到這一點,但是它滿足了問題的約束。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.