繁体   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