【问题标题】:What is the time complexity of name look-up in an R list?在 R 列表中查找名称的时间复杂度是多少?
【发布时间】:2017-05-12 05:17:08
【问题描述】:

我拼命想通过谷歌找到答案,但失败了。我即将自己进行基准测试,但我想也许这里有人知道答案,或者至少是记录在案的参考。

扩展我的问题:假设我在 R 中有一个长度为 N 的列表 L,其中 N 相当大(例如,10000、100.000、100 万或更多)。 假设我的列表中每个元素都有名称。 `

我想知道检索单个命名条目需要多长时间,即做

 L[[ "any_random_name" ]]  

这个时间是O(N),即与列表长度成正比,还是O(1),即与列表名称无关的常数。还是O( log N )

【问题讨论】:

标签: r list time-complexity lookup


【解决方案1】:

有趣的是,答案竟然是两个O(1)O(n)。时机与其说取决于列表的长度,不如说是在获得你想要的命名元素之前的列表长度。

让我们定义一些不同长度的列表:

library(microbenchmark)

makelist <- function(n){
   L <- as.list(runif(n))   
   names(L) <- paste0("Element", 1:n)
   return(L)
}

L100 <- makelist(100)
L1000 <- makelist(1000)
LMillion <- makelist(10^6)
L10Million <- makelist(10^7)

如果我们尝试从其中的每一个中提取名为 Element100our 的元素 - 第 100 个元素 - 所需的时间长度基本相同:

microbenchmark(
   L10Million[["Element100"]],
   LMillion[["Element100"]],
   L1000[["Element100"]],
   L100[["Element100"]]
)

Unit: nanoseconds
                       expr min  lq    mean median   uq   max neval cld
 L10Million[["Element100"]] 791 791  996.59    792 1186  2766   100   a
   LMillion[["Element100"]] 791 791 1000.56    989 1186  1976   100   a
      L1000[["Element100"]] 791 791 1474.64    792 1186 28050   100   a
       L100[["Element100"]] 791 791 1352.21    792 1186 17779   100   a

但是如果我们尝试获取最后一个元素,需要的时间是O(n)

microbenchmark(
   L10Million[["Element10000000"]],
   LMillion[["Element1000000"]],
   L1000[["Element1000"]],
   L100[["Element100"]]
)

Unit: nanoseconds
                            expr       min        lq         mean    median        uq       max neval cld
 L10Million[["Element10000000"]] 154965791 165074635 172399030.13 169602043 175170244 235525230   100   c
    LMillion[["Element1000000"]]  15362773  16540057  17379942.70  16967712  17734922  22361689   100  b 
          L1000[["Element1000"]]      9482     10668     17770.94     16594     20544     67557   100 a  
            L100[["Element100"]]       791      1186      3995.15      3556      6322     24100   100 a 


library(ggplot2)
library(dplyr)
res <- data.frame(x = c(100, 1000, 10^6, 10^7), 
           y = c(3556, 16594, 16967715, 169602041)) 

ggplot(res, aes(x = x, y = y ))+
   geom_smooth(method = "lm") +
   geom_point(, size = 3) +
   scale_x_log10() +
   scale_y_log10()

【讨论】:

  • 不错的答案——但说它既是O(1) 又是O(n) 是苹果和橘子的比较。 O(n) 描述了最坏的情况——这是通常衡量复杂性的方式。 (几乎)最佳案例是O(1),这并不奇怪。 Average 情况(从一组有效名称中随机选择名称)也将是 O(n)
  • WTF,不是两者兼而有之。答案就是 O(n)。
  • @Nevin 我的意思是,这取决于您要查找的命名元素。正如我所展示的,当您查找早期元素之一时向列表中添加更多元素不会增加搜索时间。你可以说这是不太可能的用例,但它不值得“wtf”。 John Coleman 的评论是一个更好的回应。
【解决方案2】:

名称查找的最坏情况是 O(n)。看这里:https://www.refsmmat.com/posts/2016-09-12-r-lists.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-16
    • 2012-04-06
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    相关资源
    最近更新 更多