【问题标题】:Find out if any two elements in a list sum to a specific value in R找出列表中的任何两个元素总和是否等于 R 中的特定值
【发布时间】:2021-02-23 02:22:14
【问题描述】:

这是一个经典的面试问题。给定一个列表numbers 和一个特定值k,找出numbers 中的任何两个元素相加后是否等于k。在r 中如何通过单遍算法而不是穷举搜索来解决这个问题?

实际上:在r 中编写最优函数,接收列表numbers 和特定值k,如果numbers 中有两个元素相加等于@,则返回TRUE 987654331@。如果没有,请返回FALSE

【问题讨论】:

    标签: r logic


    【解决方案1】:

    这个问题可以表述为:numbers中是否有ab,例如: a + b = k?考虑到您已经知道k,并假设实际上有两个数字相加等于k,可以假设:

    a = k - bb = k - a

    因此,通过k - numbers,我们基本上可以求解上述两个方程的右侧。例如:

    numbers <- c(10, 12, 6, 3)k <- 9k - numbers 将返回 c(-1, -3, 3, 6)。看看 3 和 6 是怎么出现的?

    要在 R 中完成所有这些,可以定义一个函数

    sum_finder <- function(numbers, k) {
        diff_sequence <- k - numbers
        condition <- any(numbers %in% diff_sequence)
        return(condition)
    }
    

    或者简单地说:

    sum_finder <- function(numbers, k) {
        return(any(numbers %in% (k - numbers)))
    }
    

    编辑:出于基准测试的目的,我将在此处发布迄今为止发布的解决方案以及使用 microbenchmark::microbenchmark() 的性能结果。

    # as posted by @eduardokapp
    function1 <- function(numbers, k) {
        any(numbers %in% (k - numbers))
    }
    
    # as posted by @AnilGoyal
    function2 <- function(numbers, k) {
        any(apply(outer(numbers, numbers, `+`), 1, function(x){x == k}))
    }
    
    # Performance Comparison
    numbers <- sample(500, 500)
    k <- sample(500, 1)
    microbenchmark::microbenchmark(
       function1(numbers, k),
       function2(numbers, k)
    )
    
    
    

    性能比较

    单位:毫秒

    expr min lq mean median uq max neval
    function1(numbers, k) 13.651 21.277 39.58225 27.4485 40.1905 277.256 100
    function2(numbers, k) 5061.088 5805.186 10971.04516 7571.6030 13316.1325 47782.874 100

    【讨论】:

      【解决方案2】:

      我认为您只能在 baseR 中使用内置函数来完成此操作

      让我演示一下-

      • 使用outer 构造一个数字向量的和矩阵,比如x。我们将中间结果命名为y
      • 使用 apply 来检查 which 元素是否等于所需的数字,例如 k。我使用了arr.ind 参数=T,所以输出再次是矩阵格式的索引。
      • 创建一个包含x 值的最终矩阵,在该矩阵中获得所需结果
      x <- 25:40
      k <- 61
      y <- outer(x, x, `+`)
      
      matrix(x[which(apply(y, 1, function(x){x == k}), arr.ind = T)], ncol = 2)
      
            [,1] [,2]
       [1,]   36   25
       [2,]   35   26
       [3,]   34   27
       [4,]   33   28
       [5,]   32   29
       [6,]   31   30
       [7,]   30   31
       [8,]   29   32
       [9,]   28   33
      [10,]   27   34
      [11,]   26   35
      [12,]   25   36
      

      我们看到 12 个值组合满足您的条件。

      • 注意 1,在这种情况下,对于像 sum 这样的任何交换运算,输出将包含镜像,如果需要,您可以通过取一半以上的值来过滤掉这些镜像。

      • 注意2如果您还想消除迭代自身的值,您可以在继续之前设置diag(y) &lt;- 0diag(y) &lt;- NA

      编辑鉴于修改后的要求,这样做

      x <- 25:40
      k <- 61
      
      sum(outer(x, x, `+`) == k) > 0
      [1] TRUE
      
      #OR
      x <- 1:6
      k <- 1
      
      sum(outer(x, x, `+`) == k) > 0
      [1] FALSE
      

      【讨论】:

      • 感谢您的回复。但是,我相信之前发布的解决方案也使用了 base R 并且看起来更简单一些?我错过了什么吗?谢谢你:)
      • 我还要补充一点,如果有任何两个元素满足问题,则无论您使用什么操作都应该返回 TRUE,否则返回 FALSE。
      • 注册您的第一条评论 - 这是个人选择,因为两种情况下的结果格式不同。注册您的第二条评论 - 实际上,如果这是唯一的要求,它非常简单,无需编写任何自定义函数即可完成。我正在编辑答案以纳入此要求。
      • 我还想补充一点,这是一种很好的做法,即接受您认为正确的任何答案。但是,您可以对每个问题仅接受一个答案。您仍然可以为每个问题投票,只要您觉得正确。
      • 当然!如果您认为其他答案不正确,我只是好奇。我喜欢你的编辑,没想过使用outer。作为建议,也许将sum() &gt; 0 更改为any()?哪个更快?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-17
      • 2012-09-28
      • 1970-01-01
      • 2022-07-22
      • 2012-10-15
      • 2020-02-10
      • 1970-01-01
      相关资源
      最近更新 更多