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

标签 c++ arrays ternary-search

An 个正整数的数组。

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

最佳答案

left(k) 表示数组中从 A[0]A[k] 的值的总和。证明是微不足道的:

 left(k+1)=left(k)+A[k+1]

就是这样,如果您已经为给定的 k 计算了您的 left,那么 k+1left > 通过将下一个元素添加到 left 来计算。

换句话说:

如果您遍历数组,从元素 #0 到元素 #n-1(其中 n 是数组的大小),您可以计算 left< 的运行总计 只需将数组中的下一个元素添加到 left

这似乎是显而易见且不言而喻的,但正式地说明这一点有助于流程的下一步变得同样显而易见。

同理,给定right(k)表示数组中从元素#k开始,直到数组最后一个元素的值之和,你也可以证明如下:

right(k+1)=right(k)-A[k]

因此,您可以找到 left(k)right(k+1) 之间的差异最小的 k (I' m 使用与你的问题使用的符号略有不同,因为我的符号更方便)从数组中所有值的总和开始作为 right(0)A[0] left(0),然后计算right(1),然后,从头开始迭代数组到尾,计算两个leftright 在每个步骤中,即时计算左右值之间的差异。找到差异最小的地方变得微不足道。

我想不出任何其他方式来做到这一点,不到 O(n):

1) 计算数组中所有值的总和,因为right(0)的初始值为O(n)。

2) 右边的迭代当然是 O(n)。

我不相信对数二分查找在这里起作用,因为值 abs(left(k)-right(k)) 本身不会按排序顺序排列。

顺便说一句,使用这种方法,当数组也包含负值时,您也可以找到最小差值。唯一的区别是,由于差异不再是抛物线,您只需遍历整个数组,只需跟踪 abs(left-right) 最小的位置即可。

关于c++ - 三元搜索以在数组中找到差异最小的点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37911533/

相关文章:

c++ - 如何使用Qt检查webservice是否启动

C++ 相互模板依赖?

arrays - 对 m 维上的 n 维数组求和的最紧凑方法

algorithm - 为什么k元搜索的比较平均是k*ln(N)/ln(k)?

algorithm - 三元搜索如何应用于 SPOJ 挑战 - KOPC12A

c++ - 将结构指针复制到指针

c++ - 在 Qt 中使用进度回调的 CopyFileEx

python - 如何将多维数组从一种特定排列 reshape 为另一种排列?

arrays - 为什么我不能访问以寄存器作为偏移量的数组?