在保持顺序的同时对循环缓冲区进行分区

时间:2013-11-15 16:17:15

标签: algorithm

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

  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

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

1 个答案:

答案 0 :(得分:5)

算法:

  1. 计算总金额。

  2. 让当前的总和= 0。

  3. 在任何一点开始时都会指向2个指针(两个指针都在同一点开始)。

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

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

  6. 如果有的话停止:

    • 第一个指针返回它开始的位置,或

    • 最佳总和是总和的一半的0.5或0(在这种情况下差异将是1或0)。

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

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

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

    运行时间:

    运行时间将为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
    

    sum = 0

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

    sum = 1

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

    sum = 6

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

    sum = 8

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

    sum = 15

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

    sum = 24

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

    sum = 23

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

    sum = 18

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

    sum = 20

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

    上述内容对应(11 4 1 5) (2 7 9 2)1的总和不同。