让 A n 正整数数组。
如何找到A的索引k,使得:
left = A[0] + A[1] + ... + A[k]
right = A[k+1] + A[k+2] + ... + A[n]
有最小的绝对差值(即abs(left - right)
是最小的)?
由于这个差异的绝对函数是抛物线的(减小到最小差值然后增加,就像 U ),我听说三元搜索用于在这样的函数中找到值(抛物线) ),但我不知道如何实现它,因为我通过互联网搜索并没有找到使用三元搜索而不是抛物线函数。
编辑:假设我在O(1)中有所有区间和,我需要比O(n)更快的东西,否则我不需要三元搜索..
答案 0 :(得分:2)
让left(k)
代表数组中值的总和,从A[0]
到A[k]
。证明:
left(k+1)=left(k)+A[k+1]
如果您已经为给定的left
计算了k
,那么left
的{{1}}就会通过将下一个元素添加到k+1
来计算
换句话说:
如果迭代数组,从元素#0到元素#n-1(其中left
是数组的大小),只需添加n
即可计算出{}的运行总计数组中的下一个元素为left
。
这似乎是显而易见且不言自明的,但它有助于正式说明这一点,以使该过程的下一步变得同样显而易见。
以相同的方式,给定left
表示以元素#k开头的数组中的值的总和,直到数组中的最后一个元素,您还可以证明以下内容:
right(k)
因此,您可以找到right(k+1)=right(k)-A[k]
与k
和left(k)
之间的最小差异(我使用与您的问题使用的略有不同的符号,因为我的符号是更方便)首先将数组中所有值的总和作为right(k+1)
和right(0)
作为A[0]
,然后计算left(0)
,然后从头开始迭代到数组到最后,在每一步计算right(1)
和left
,并计算左右值之间的差异。找出差异最小的地方变得微不足道。
在right
之内,我无法想到其他任何方式:
1)计算数组中所有值的总和,初始值O(n)
为O(n)。
2)右边的迭代当然是O(n)。
我不相信对数二进制搜索在这里可行,因为值right(0)
本身不会按排序顺序。
顺便说一下,使用这种方法,您也可以在数组包含负值时找到最小差异。唯一的区别是,由于差异不再是抛物线的,您只需要遍历整个数组,然后跟踪abs(left(k)-right(k))
最小的位置。
答案 1 :(得分:-1)
琐碎的方法:
A[0] + A[1] + ... + A[k]
的所有金额A[k+1] + A[k+2] + ... + A[n]
和k<=n
。k
abs(left - right)
最小化k<=n
。{
醇>
空间和时间 O(n)
。
编辑:
计算所有总和可以使用增量方法在O(n)
中完成。