荣誉版主
- 积分
- -2403
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2010-5-4
- 最后登录
- 1970-1-1
|
对三个数组排序,时间复杂度nlogn
做一个三路merge sort, 每次对A,B,C中最小的a,b,c三个数做判断,同时更新结果。
在a,b,c中取最小的数x, x进到下一个元素,这样新的3元素对就形成了。
这是解法,证明这个解法的正确性比较麻烦。同时要证明加入a == b < c, 那么是递增A数组还是B数组。
需要证明递增A,B可以,结果都是一样的。这套证明的关键就是你指出的|a-b|+|b-c|+|c-a| 只和最大最小的两个元素相关,和中间那个无关,每一个iteration唯一可以改良的办法就是递增最小元素所在的那个数组。
int CalcABS(int a, int b, int c)
{
return abs(a-b) + abs(a-c) + abs(b-c);
}
int GetMin(vector<int>& vec)
{
assert(!vec.empty());
int nMin = vec[0];
for (int i = 0; i < vec.size(); i++)
{
if (vec[i] < nMin)
nMin = vec[i];
}
return nMin;
}
int GetABC(int a[], int na, int b[], int nb, int c[], int nc, int& sa, int& sb, int& sc)
{
assert(a && na>0 && b && nb>0 && c && nc>0);
sort(a, a+na);
sort(b, b+nb);
sort(c, c+nc);
int i = 0;
int j = 0;
int k = 0;
sa = sb = sc = 0;
int nMin = CalcABS(a[i], b[j], c[k]);
while (i != na-1 || j != nb-1 || k != nc-1)
{
vector<int> vec;
if (i != na-1) vec.push_back(a[i]);
if (j != nb-1) vec.push_back(b[j]);
if (k != nc-1) vec.push_back(c[k]);
int nRes = GetMin(vec);
if (i != na-1 && a[i] == nRes)
i++;
else if (j != nb-1 && b[j] == nRes)
j++;
else k++;
nRes = CalcABS(a[i], b[j], c[k]);
if (nRes < nMin)
{
sa = a[i];
sb = b[j];
sc = c[k];
nMin = nRes;
}
}
return nMin;
} |
|