【问题标题】:Partitioning a circular buffer while keeping order在保持顺序的同时对循环缓冲区进行分区
【发布时间】:2013-11-16 01:13:28
【问题描述】:

我有一个具有正自然值的循环缓冲区,例如

  1  5
4      2
11     7
  2  9

我们将把它分成两个连续的部分,同时保持这个顺序。本例中的这两部分可能是:

  • (4 1 5)(2 7 9 2 11),
  • (7 9 2 11 4)(1 5 2),

这个想法是保持顺序并取两个连续的子序列。

现在的问题是对它进行分区,使这些子序列的总和彼此接近,即总和之间的差必须最接近于零

在这种情况下,我认为解决方案是:(2 7 9 2)(11 4 1 5) 分别为 2021

如何以最佳方式做到这一点?

【问题讨论】:

  • 在计算成本的意义上是最优的还是只是最优解?
  • @arturgrzesiak 计算成本。我们可以使用朴素的方法在二次时间内找到最佳解决方案,对吧? :)
  • 应该是线性的 - 见 Dukelings 的帖子

标签: algorithm


【解决方案1】:

算法:

  1. 计算总和。

  2. 令当前总和 = 0。

  3. 从任意点的 2 个指针开始(都从同一点开始)。

  4. 增加第二个指针,加上它传递的数字,直到当前总和超过总和的一半。

  5. 增加第一个指针,减去它传递的数字,直到当前和小于总和的一半。

  6. 如果出现以下任一情况则停止:

    • 第一个指针回到它开始的地方,或者

    • 最好的和是总和的一半的 0.5 或 0(在这种情况下,差值为 1 或 0)。

      只有当总和为奇数时,差才能为 1,在这种情况下,差永远不能为 0。(感谢 Artur!)

  7. 否则从第 3 步开始重复。

检查我们在此过程中获得的所有当前总和,并保留最接近一半的总和,以及获得该总和的分区的索引。

运行时间:

运行时间将是O(n),因为我们只会增加指针,第一个只能转一次,第二个不能转超过两次。

示例:

输入:

  1  5
4      2
11     7
  2  9

总和 = 41。

总和的一半 = 20.5。

所以,假设我们从 1 开始。(我只是把它放在一条直线上以便更容易绘制)

p1, p2
V
 1  5  2  7  9  2  11  4

总和 = 0

p1 p2
V  V
 1  5  2  7  9  2  11  4

总和 = 1

p1    p2
V     V
 1  5  2  7  9  2  11  4

总和 = 6

p1       p2
V        V
 1  5  2  7  9  2  11  4

总和 = 8

p1          p2
V           V
 1  5  2  7  9  2  11  4

总和 = 15

p1             p2
V              V
 1  5  2  7  9  2  11  4

总和 = 24

   p1          p2
   V           V
 1  5  2  7  9  2  11  4

总和 = 23

      p1       p2
      V        V
 1  5  2  7  9  2  11  4

总和 = 18

      p1          p2
      V           V
 1  5  2  7  9  2  11  4

总和 = 20

这里总和 (20) 是总和 (20.5) 的一半的 0.5,所以我们可以停止。

上面对应(11 4 1 5) (2 7 9 2),总和相差1

【讨论】:

  • +1 我能想到的唯一改进是在差为零(如果总和为偶数)或差为一(如果总和为奇数)时停止算法。
  • @arturgrzesiak 谢谢!已编辑。
猜你喜欢
  • 2013-09-26
  • 2013-05-10
  • 2010-09-21
  • 1970-01-01
  • 1970-01-01
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多