簡體   English   中英

確定大小為n的數組中的所有重復項,其中O(1)空間和O(n)時間內的值范圍為0到n-2

[英]Determine all duplicates in array of size n having values in range 0 to n-2 in O(1) space and O(n) time

給出了大小為n的整數數組。 它只能包含0到n-2范圍內的值。 數組中可能有多個重復項。 有沒有辦法在不修改數組的情況下確定O(n)時間和O(1)空間中所有可能的重復項?

有算法在這里 ,但修改該數組。 還有另一種算法, 在這里 ,但我可以看到它不僅決定了副本之一。 有沒有辦法確定所有重復項?

如果數組中的數字是任意的,我認為沒有任何方法可以在低於O(n 2 )的情況下進行。

但是,我會仔細研究數據的限制,可能的值必須從0n-2 這允許你引入一個效率,雖然我認為不會讓你從O(n 2 )回到O(n),但至少會大大提高算法的運行時間

這是它的工作原理。 考慮從0..9范圍內繪制的十個數字:

0 1 2 3 4 5 6 7 8 9

現在介紹一個副本:

0 1 2 3 4 5 6 2 8 9

你應該注意的一件事是,重復的引入在所使用的數字集中打開了一個漏洞 - 列表中不再有7

實際上,對於您引入的每個重復項, 可能的值都會完全消失,您可以使用該事實來優化算法。 這里的技巧是不在列表中搜索每個可能的數字,而是使用每個搜索來計算出你應該尋找的下一個數字(最大數字大於當前數字)。 考慮13元素列表:

{0, 1, 1, 1, 2, 3, 0, 7, 9, 3, 9, 3, 9}

首先,我們搜索0 我們發現它是重復的,但我們發現下一個可能的數字是1所以我們記住下一個階段。

同上,用於接下來的幾個地方,我們尋找的迭代1 (一式兩份),並在未來的2 ,然后搜索2 (唯一的),下一個是3

但在這里它變得有趣。 當我們搜索3 (一式兩份),我們發現,在未來可能的數字實際上是7 ,所以我們完全可以跳過456 當然,出於同樣的原因我們跳過8 (當搜索7 ,我們發現下一個是9 )。

當我們搜索9 ,沒有下一個可能的術語,所以我們可以在那時停下來。

在偽代碼1中 ,這將是:

list = [0,1,1,1,2,3,0,7,9,3,9,3,9]
n = len(list)

# Initial search term and begin loop for each term.

currN = 0
while currN <= n - 2:
    print ("Checking for %d"%(currN))

    # Next search term, initially beyond max, and dupe detector.

    nextN = n
    count = 0

    # Check every list value.

    for val in list:
        # Count occurrences.

        if val == currN:
            count += 1

        # Update next search term if needed. If no value
        #   between curr and n, nextN will remain at n
        #   and loop will exit.

        if val > currN and val < nextN:
            nextN = val

    # Inform if duplicated and move to next search term.

    if count > 1:
        print ("%d is duplicated"%(currN))

    currN = nextN

如果您想要更高的性能,還有另一種可能的優化。 目前,您在每次迭代時檢查列表中的每個值,但這不是必需的。

例如,一旦你檢查了0 ,就沒有必要再次檢查第一個索引{0} ,因為它永遠不會再對結果產生影響。

同樣,一旦你檢查了1 ,你再也不需要重新訪問前四個元素{0, 1, 1, 1} 0,1,1,1 {0, 1, 1, 1}了。

因此,不僅要記住下一個可能的搜索詞而且還要記住可以找到它的最早點,以便以后的迭代在搜索中處理更少的元素。

可行的方法是從最初位於列表開頭的變量點搜索。 但是,在每次傳遞時,您都會將此點更新為列表中的第一個項目,該項目大於您當前正在處理的搜索項。


如上所述,我不相信這些建議中的任何一個會給你O(n),但它肯定比天真的方法更好。 它的范圍從接近n * n的操作對於其中沒有重復的情況下(例如, {1, 2, 3, 4}下降到約n操作,其中僅存在在列表中的單個復制值(例如, {1, 1, 1, 1} )。

重復次數越多,運行時間就越好。


1 ...看起來像Python3代碼一樣可疑:-)

暫無
暫無

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

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