三元搜索在数组中找到差异最小的点

时间:2016-06-19 20:29:37

标签: c++ arrays ternary-search

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)更快的东西,否则我不需要三元搜索..

2 个答案:

答案 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] kleft(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)

琐碎的方法:

  1. 计算所有A[0] + A[1] + ... + A[k]的所有金额A[k+1] + A[k+2] + ... + A[n]k<=n
  2. k
  3. 搜索abs(left - right)最小化k<=n。{ 空间和时间

    O(n)

    编辑: 计算所有总和可以使用增量方法在O(n)中完成。