【发布时间】:2021-02-23 02:22:14
【问题描述】:
这是一个经典的面试问题。给定一个列表numbers 和一个特定值k,找出numbers 中的任何两个元素相加后是否等于k。在r 中如何通过单遍算法而不是穷举搜索来解决这个问题?
实际上:在r 中编写最优函数,接收列表numbers 和特定值k,如果numbers 中有两个元素相加等于@,则返回TRUE 987654331@。如果没有,请返回FALSE。
【问题讨论】:
这是一个经典的面试问题。给定一个列表numbers 和一个特定值k,找出numbers 中的任何两个元素相加后是否等于k。在r 中如何通过单遍算法而不是穷举搜索来解决这个问题?
实际上:在r 中编写最优函数,接收列表numbers 和特定值k,如果numbers 中有两个元素相加等于@,则返回TRUE 987654331@。如果没有,请返回FALSE。
【问题讨论】:
这个问题可以表述为:numbers中是否有a和b,例如:
a + b = k?考虑到您已经知道k,并假设实际上有两个数字相加等于k,可以假设:
a = k - b 或b = k - a。
因此,通过k - numbers,我们基本上可以求解上述两个方程的右侧。例如:
numbers <- c(10, 12, 6, 3) 和 k <- 9。 k - 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 |
【讨论】:
我认为您只能在 baseR 中使用内置函数来完成此操作
让我演示一下-
outer 构造一个数字向量的和矩阵,比如x。我们将中间结果命名为y
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) <- 0或diag(y) <- 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
【讨论】:
outer。作为建议,也许将sum() > 0 更改为any()?哪个更快?