[英]How to find a number that was repeated (n/3) times an array of size n, in O(n) time and O(n) space?
[英]Determine all duplicates in array of size n having values in range 0 to n-2 in O(1) space and O(n) time
如果數組中的數字是任意的,我認為沒有任何方法可以在低於O(n 2 )的情況下進行。
但是,我會仔細研究數據的限制,可能的值必須從0
到n-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
,所以我們完全可以跳過4
, 5
和6
。 當然,出於同樣的原因我們跳過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.