簡體   English   中英

我的算法的時間復雜度是 O(n log n) 嗎?

[英]Is my algorithm's time complexity O(n log n)?

def two_sum1?(array, value)
    array.sort! # O(nlogn)
    array.each do |element|
        return true if bsearch(array - [element], value - element) == true
    end
    return false
end

def bsearch(array, value)
    return false if array.empty?
    mid_idx = array.length / 2
    mid_value = array[mid_idx]
    return true if mid_value == value
    mid_value < value ? bsearch(array[0...mid_idx], value) : bsearch(array[mid_idx+1..-1], value)
end

我正在嘗試創建一個 function 在數組中找到兩個唯一數字,使它們的總和等於第二個參數中的值。 我相信我的實現的時間復雜度為 O(n log n)。 但是,當我使用另一個時間復雜度也是 O(n log n) 的 function 運行它時,使用相同輸入的總時間是不同的(使用 Benchmark gem 計算)。 對於我的 function,大約需要 0.9 秒。 對於另一個 function,它需要 0.003 秒。 我的算法分析有錯誤嗎? 我的實現不是 O(n log n) 嗎?

這是另一個 function:

def two_sum2?(arr, target_sum)
  arr = arr.sort
  arr.each_with_index do |el, i|
    match_idx = arr.bsearch_index { |el2| (target_sum - el) <=> el2 }
    return true if match_idx && match_idx != i
  end
  false
end

這是我用來測試這兩個功能的:

arr = [0, 1, 5, 7] + [100] * 10000
puts Benchmark.measure { two_sum1?(arr, 6) }
puts Benchmark.measure { two_sum1?(arr, 8) }
puts Benchmark.measure { two_sum1?(arr, 10) }
puts Benchmark.measure { two_sum2?(arr, 6) }
puts Benchmark.measure { two_sum2?(arr, 8) }
puts Benchmark.measure { two_sum2?(arr, 10) }

不,它是 O(n^2)。

array[0...mid_idx] (即切片)每次都會創建一個新數組 因此, bsearch不是 log(n),而是 n。

此外,嘗試將 bsearch 從遞歸方法重寫為迭代。 它工作得更快。 喜歡這里

您創建的算法通常看起來是正確的。 讓我們試着分析一下它的復雜性。 如果正確實施,您的排序應該是O ( n log n )。 現在,讓我們假設您的bsearch已正確實現(這意味着它的復雜度為O (log n )),那么您將獲得整個循環O ( n log n )。 這仍然意味着算法是O ( n log n )。

現在讓我們 go 來執行bsearch 正如我所說,它通常是正確的(盡管如果您的數組具有奇數個元素,您可能應該考慮使用選擇索引更改部分),它失敗的地方是數組切片。 每當您對數組進行切片end ,它都會在內部迭代切片中給定的start的元素數量並將它們復制到新數組中,這會破壞復雜性並使其成為O ( n ) 而不是O (log n ) 並且從而使整個算法O ( n 2 ),因為循環。

暫無
暫無

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

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