【问题标题】:count of sequences of array elements with appropriate sum具有适当总和的数组元素序列的计数
【发布时间】:2016-10-18 20:43:54
【问题描述】:

假设我们有一个未排序的整数数组和 2 个给定的整数 L 和 M。我们的任务是找到具有以下属性的序列 a[i]...a[j] 的计数:L

哪种算法最适合解决这个问题?

注意:1

【问题讨论】:

  • 它看起来像段树的情况。
  • 这些整数可以是负数吗?

标签: arrays algorithm


【解决方案1】:

如果整数都是非负的,你可以使用这个算法(伪代码):

countInRange(a, l, m):
    sumL = 0
    count = 0
    idxM = 0
    i = 1
    idxLast = len(a)
    for idxL = 1 to idxLast:
        sumL = sumL + a[idxL]
        while i <= idxLast and sumL >= l:
            if idxM <= idxL:
                idxM = idxL
                sumM = sumL
            while idxM <= idxLast and sumM <= m:
                idxM = idxM + 1
                if idxM > idxLast:
                    break
                sumM = sumM + a[idxM]
            count = count + idxM - idxL
            sumL = sumL - a[i]
            sumM = sumM - a[i]
            i = i + 1
    return count

这个算法运行时间复杂度O(n)

总的来说,最里面的循环永远不会迭代超过 n 次。这是因为进入循环时idxM的值:

  • 永远不会低于 1
  • 永远不会高于 n
  • 总是比上次进入循环的时间至少大一。

总的来说,中间循环也永远不会执行超过 n 次,因为它会将 i 增加到 n,显然也是如此外循环为真。

参见this implementation in Python on repl.it,它还提供了一个O(n²) 算法来检索实际序列本身。请注意,该代码必须适应 Python 中的零索引数组。

【讨论】:

  • 谢谢你的回答。虽然结果应该是一个数字。例如,10 个序列,12 个序列或类似的东西。我们想要找到序列的数量,而不是序列本身。
  • @user3697730 只需添加计数器并在适当的位置递增它。代码
  • @user3697730,我将答案更新为仅计数。在这种情况下,算法可以在 O(n) 时间内运行,而实际序列需要报告的情况并非如此。
【解决方案2】:

我想下面的算法应该可以完成这项工作。我试图在 JS 中实现它。它基本上是一个单一的 reduce 操作,初始值类似于 {idx:0, len:0, sum:0},内部有一个 3 级嵌套三元组。

出于测试目的,我生成了一个包含 30 个项目的数组,其中随机值介于 1 到 10 之间。目前它以系列形式给出结果,以便您帮助我检查它是否运行良好。然后根据您的要求,系列很重要,我们只需要替换最后一个

return r[0].sum < low ? r.slice(1) : r;

符合

return r[0].sum < low ? r.length-1 : r.length;

function getLimitedSeries(a,low,high){
  var r = a.reduce((p,c,i) => (p[0].sum + c < low ? ( p[0].sum += c,
                                                      p[0].len++
                                                    )
                                                  : p[0].sum + c <= high ? ( p[0].sum += c,
                                                                             p[0].len++,
                                                                             p[0].idx = i-p[0].len+1
                                                                           )
                                                                         : ( p[0].sum >= low && p.push(p[0]),
                                                                             p[0] =  c > high ? {idx:i, len:0, sum:0}
                                                                                              : {idx:i, len:1, sum:c}
                                                                           ),p)
                              , [{idx:0, len:0, sum:0}]);  // initial value of reduce
  return r[0].sum < low ? r.slice(1) : r;
}

var arr = new Array(30).fill().map(e => ~~(Math.random()*10)+1);

console.log(JSON.stringify(arr));
console.log(getLimitedSeries(arr,15,21));

【讨论】:

    猜你喜欢
    • 2016-05-18
    • 1970-01-01
    • 2021-10-12
    • 2018-02-07
    • 1970-01-01
    • 2021-07-19
    • 1970-01-01
    • 2019-09-26
    • 1970-01-01
    相关资源
    最近更新 更多