我有一个具有正自然值的循环缓冲区,例如
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)
,其中包括20
和21
。
如何以最佳方式做到这一点?
答案 0 :(得分:5)
算法:
计算总金额。
让当前的总和= 0。
在任何一点开始时都会指向2个指针(两个指针都在同一点开始)。
增加第二个指针,添加它传递的数字,直到当前总和超过总和的一半。
增加第一个指针,减去它传递的数字,直到当前总和小于总和的一半。
如果有的话停止:
第一个指针返回它开始的位置,或
最佳总和是总和的一半的0.5或0(在这种情况下差异将是1或0)。
只有当总和是奇数时,差异才可以为1,在这种情况下差异永远不能为0.(感谢Artur!)
否则从第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
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
的总和不同。