问题:给定一个向量,我想知道一系列累积和的最小值,其中每个累积和计算为向量的增加起始索引和固定的结束索引(1 :5,2:5,......,5:5)。具体来说,我想知道是否可以使用for()
循环来计算这个,并且是否有可能存在此算法/计算的术语。我在R工作。
背景:感兴趣的矢量包含压力变化的时间序列。我想知道一系列起点的最大(或最小)压力净变化但是有一个固定的终点。
详情+示例:
#Example R code
diffP <- c(0, -1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0)
minNet1 <- min(cumsum(diffP))
minNet1 #over the whole vector, the "biggest net drop" (largest magnitude with negative sign) is -1.
#However, if I started a cumulative sum in the second half of diffP, I would get a net pressure change of -2.
hold <- list()
nDiff <- length(diffP)
for(j in 1:nDiff){
hold[[j]] <- cumsum(diffP[j:nDiff])
}
answer <- min(unlist(hold)) #this gives the answer that I ultimately want
希望我上面的例子有助于阐明我的问题。 answer
包含正确答案,但我宁愿在没有R中的for()
循环的情况下执行此操作。是否有更好的方法来执行此计算,或者可能是我可以添加的名称?
答案 0 :(得分:3)
这被称为http://en.wikipedia.org/wiki/Maximum_subarray_problem,是一个典型的面试问题!
大多数人 - 包括 - 将使用O(n ^ 2)算法解决它,但实际上有一个更好的算法,具有O(n)复杂度。以下是来自上面链接的Kadane算法的R实现:
max_subarray <- function(A) {
max_ending_here <- 0
max_so_far <- 0
for (x in A) {
max_ending_here <- max(0, max_ending_here + x)
max_so_far <- max(max_so_far, max_ending_here)
}
max_so_far
}
因为在你的情况下,你正在寻找最小子数组总和,你必须这样称呼它:
-max_subarray(-diffP)
[1] -2
(或者您也可以重写上述功能,并将max
替换为min
。)
注意,是的,实现仍然使用for
循环,但算法的复杂度为O(n)(意味着操作数与length(diff)
的顺序相同),它应该很快。此外,它不会消耗任何内存,因为它只存储和更新几个变量。