【问题标题】:Is this an example of logarithmic time complexity?这是对数时间复杂度的一个例子吗?
【发布时间】:2020-02-21 09:44:24
【问题描述】:

通常说具有对数时间复杂度O(log n) 的算法是输入加倍并不一定需要加倍工作量的算法。通常,搜索算法是作为具有对数复杂度的算法的示例给出的。

考虑到这一点,假设我有一个函数,它接受一个字符串数组作为第一个参数,以及一个单独的字符串作为第二个参数,并返回数组中字符串的索引:

function getArrayItemIndex(array, str) {
  let i = 0
  for(let item of array) {
    if(item === str) {
      return i
    }
    i++
  }
}

假设这个函数的调用如下:

getArrayItemIndex(['John', 'Jack', 'James', 'Jason'], 'Jack')

在这种情况下,函数在返回1 的索引之前不会遍历整个数组。同样,如果我们将数组中的项目加倍,最终调用如下:

getArrayItemIndex(
  [
    'John', 
    'Jack', 
    'James', 
    'Jason',
    'Jerome',
    'Jameson',
    'Jamar',
    'Jabar'
  ], 
  'John'
)

...然后将数组中的项目加倍不一定会导致函数的运行时间加倍,因为它会跳出循环并在第一次迭代后返回。因此,是否可以准确地说getArrayItemIndex 函数具有对数时间复杂度?

【问题讨论】:

  • 通常说,具有对数时间复杂度 O(log n) 的算法是这样一种算法,其中将输入加倍并不一定会使所需的工作量加倍。对数并不意味着“不一定是线性的”。

标签: time-complexity complexity-theory


【解决方案1】:

不完全是。您在这里拥有的是线性搜索。它最差的情况是 Theta(n),因为如果搜索目标不在列表中,它必须检查所有元素。您发现它的最佳情况是 Theta(1),因为如果幸运的话,该算法只需要运行几次检查。

对预排序数组的二分搜索是 O(log n) 最坏情况算法的一个示例(最好的情况仍然是 O(1))。它的工作原理是这样的:

检查中间元素。如果匹配,则返回。否则,如果元素太大,则对数组的前半部分执行二进制搜索。如果它太大,则在后半部分执行二进制搜索。继续直到找到目标或用完要检查的新元素。

在二分搜索中,我们从不查看所有元素。这就是区别。

【讨论】:

  • 非常感谢您的回答。真的很感激。所以我得到的是,我们总是关心最坏的情况。换句话说,如果最坏的情况是 O(log n),它只会是 O(log n)。在我的示例中,最坏的情况是数组被完全循环,总共循环一次,这是一个线性(即 O(n))操作。然而,对于二进制搜索示例,因为我们永远不会查看数组中的每个元素,即使在最坏的情况下,这意味着该操作是 O(log n) 操作......看到最坏的情况,它是 O (日志 n)。对吗?
  • @JairusRuth 这听起来像是一个正确的总结,是的。我要补充一点,考虑除最坏情况以外的情况(或除上限以外的界限)在技术上并没有错,但通常情况下,最坏情况的上限是人们所谈论的 w.r.t.算法,因为这与底层问题的复杂性类别有关。
猜你喜欢
  • 2021-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-03
  • 2017-09-11
  • 1970-01-01
  • 2021-12-16
  • 2015-02-18
相关资源
最近更新 更多