簡體   English   中英

查找特定的缺失數組元素:O(n + k)復雜度

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

我們將這些時間復雜度加起來如下:

 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.

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