三个阵列中的三个附近数字

时间:2014-07-19 12:22:54

标签: arrays algorithm sorting

给定三个已排序的浮点数组a[]b[]c[],设计一个线性算法来查找三个整数ijk使|a[i] - b[j]| + |b[j] - c[k]| + |c[k] - a[i]|最小化。

我确实有一个解决方案,但我不认为这是线性的。这就是我现在所拥有的:

 assume minDiff = // some huge value

 for each entry in 'a'
   find an entry closest to it in 'b' and call it 'closestToA'
   find an entry closest to 'closestToA' in 'c' and call it 'closestToB'
   compute the diff: 
         int currDiff = Math.abs(a[i] - closestToA) + Math.abs(closestToA - closestToB) + Math.abs(closestToB - a[i]);
   Replace minDiff with currDiff, if currDiff < minDiff

首先,我想知道是否有更好的解决方案?如果没有,那么我认为这个解决方案没有线性复杂性吗?可以使用二分查找找到最接近的数字。

问题来自&#34;算法 - 第四版。&#34;罗伯特塞奇威克和凯文韦恩以及我正在为即将到来的采访做准备。

有些类似的问题:Match Three or More Nearest Numbers from arrays

2 个答案:

答案 0 :(得分:2)

让我们看看元素的一些潜在排序:

a[i] < b[j] < c[k]

然后我们可以看到以下声明:

Target = |a[i] - b[j]| + |b[j] - c[k]| + |c[k] - a[i]|
       = b[j] - a[i] + c[k] - b[j] + c[k] - a[i]
       = 2 * (c[k] - a[i])

因此,对于任何可能的排序,这是两个不同阵列中两个元素之间差异的最小化。因此,只需最小化每个可能的组合(abbcca),如问题所示你给了一个参考(可以在每对的线性时间内完成)。

一旦找到一对的最小化,找到第三个数组中的匹配元素应该非常简单 - 只需遍历该数组并检查每个元素。

答案 1 :(得分:2)

以下算法几乎就像将三个已排序的数组合并为一个已排序的数组。

为每个数组保留一个指针(分别为A,B和C的i,j,k)。将它们初始化为0。

然后计算A [i],B [j],C [k]之间的差异,并在必要时更新到目前为止所达到的最低值。

增加

数组中的索引
array[index] =  min(A[i], B[j] and C[k]) 

如果尚未到达终点。

那是:

If ( A[i] is the least ), then increment i.
else If ( B[j] is the least ), then increment j.
else increment k.

继续执行上述操作,直到任何一个索引超过结尾,或者您发现所有三个A [i],B [j]和C [k]相等的情况。

修改
如果有两个重复的候选者(比如A [i] == B [j]),则递增i和j。看看为什么。

另外,如果A [i + 1] == A [i],则再简单地增加i 结束编辑:

上述算法具有O(N)时间复杂度。

正确性证明:
如其他答案所示,差异仅取决于A [i],B [j],C [k]的两个极端。

所以如果A [i]&lt; B [j]&lt; C [k],则差= 2 *(C [k] - A [i])。因此,如果我们增加j或k,那么差异只会增加。因此我们增加i。