具有不同起始指数的累积总和的最小值

时间:2013-08-28 19:15:41

标签: r algorithm time-series cumulative-sum

问题:给定一个向量,我想知道一系列累积和的最小值,其中每个累积和计算为向量的增加起始索引和固定的结束索引(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()循环的情况下执行此操作。是否有更好的方法来执行此计算,或者可能是我可以添加的名称?

1 个答案:

答案 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)的顺序相同),它应该很快。此外,它不会消耗任何内存,因为它只存储和更新几个变量。