您将获得三个排序的数组(按升序排列),您需要找到三元组(每个数组中的一个元素),以使距离最小。
距离定义如下:
如果a[i], b[j]
和c[k]
是三个元素,那么
distance = max{abs(a[i]-b[j]),abs(a[i]-c[k]),abs(b[j]-c[k])}
请提供O(n)时间复杂度的解决方案
答案 0 :(得分:4)
线性时间算法:
double MinimalDistance(double[] A, double[] B, double[] C)
{
int i,j,k = 0;
double min_value = infinity;
double current_val;
int opt_indexes[3] = {0, 0, 0);
while(i < A.size || j < B.size || k < C.size)
{
current_val = calculate_distance(A[i],B[j],C[k]);
if(current_val < min_value)
{
min_value = current_val;
opt_indexes[1] = i;
opt_indexes[2] = j;
opt_indexes[3] = k;
}
if(A[i] < B[j] && A[i] < C[k] && i < A.size)
i++;
else if (B[j] < C[k] && j < B.size)
j++;
else
k++;
}
return min_value;
}
在每个步骤中检查当前距离,然后递增当前指向最小值的数组的索引。每个数组只迭代一次,这意味着运行时间为O(A.size + B.size + C.size)
。
如果您想要最佳索引而不是最小值,则可以返回opt_indexes
而不是min_value
。
答案 1 :(得分:1)
假设我们只有一个已排序的数组,那么具有较少可能距离的3个连续元素是所需的解决方案。现在当我们有三个数组时,只需将它们全部合并并制作一个大的排序数组ABC(这可以通过合并排序中的合并操作在O(n)中完成),只需保留一个标志来确定哪个元素属于哪个原始数组。现在你必须在数组中找到三个连续的元素:
a1,a2,b1,b2,b3,c1,b4,c2,c3,c4,b5,b6,a3,a4,a5,....
并且此处连续表示它们按连续顺序属于3个不同的组,例如:a2,b3,c1或c4,b6,a3。
现在找到这个树元素并不难,确定最小和最大的元素应该是最后的,并且在某些三元组中的第一个和最后一个元素的元素中的第一个,例如在组中:[c2,c3,c4],[b5, b6],[a3,a4,a5],我们不需要检查a4,a5,c2,c3
很明显,在这种情况下可能的解决方案是c4,[b5,b6],a5,我们也不需要将c4与b5,b6或a5与b5,b6进行比较,确定距离由a5-c4(在该组中)进行。因此,我们可以从左开始并跟踪最后一个元素,并通过保留每个组的最后访问值来更新每个迭代中的最佳解决方案。
示例(首先我应该说我没有编写代码,因为我认为这是OP的任务而不是我):
假设我们在排序数组后有这个序列:
a1,a2,b1,b2,b3,c1,b4,c2,c3,c4,b5,b6,a3,a4,a5,....
让我们一步一步地迭代:
我们需要跟踪数组中每个项目的最后一项,a
用于跟踪当前最佳a_i,b代表b_i,c代表c_i。首先假设a_i = b_i = c_i = -1,
在第一步中a将是a1,在下一步
a=a2,b=-1,c=-1
a=a2,b=b1,c=-1
a=a2,b=b2,c=-1
a=a2,b=b3,c=-1,
a=a2,b=b3,c=c1,
此时我们将当前指针(a2,b3,c1)保存为差值的最佳值,
下一步:
a=a2,c=c1,b=b4
现在我们比较b4-a2与之前最佳选项的区别,如果更好,我们将此指针保存为现在的解决方案,我们继续:
a=a2,b=b4,c=c2 (again compare and if needed update the best solution),
a=a2,b=b4,c=c3 (again ....)
a=a2,b=b4,c=c4 (again ....)
a=a2, b=b5,c=c4, ....
好的,如果从文本中不清楚,合并后我们有(我猜所有数组都至少有一个元素):
解决方案=无限; A = B = C = -1, BESTA = bestB = bestC = 1;
for (int i=0;i<ABC.Length;i++)
{
if(ABC[i].type == "a") // type is a flag determines
// who is the owner of this element
{
a=ABC[i].Value;
if (b!=-1&&c!=-1)
{
if (max(|a-b|,|b-c|,|a-c|) < solution)
{
solution = max(|a-b|,|b-c|,|a-c|);
bestA= a,bestB = b,bestC = c;
}
}
}
// and two more if for type "b" and "c"
}
当然有比这更优雅的算法,但我发现你的链接有问题,所以我想这种看待问题的简单方法会让你更容易,之后你就可以理解你自己的链接了。