已知三个升序整数数组a[l], b[m]和c[n]。请在三个数组中各找一个元素,使得组成的三元组距离最小。三元组的距离定义是:假设a[i], b[j]和c[k]是一个三元组,那么距离为:
distance = max(|a[i] - b[j]|, |a[i] - c[k]|, |b[j] - c[k]|)
distance = max(|a[i] - b[j]|, |a[i] - c[k]|, |b[j] - c[k]|)
请设计一求最小三元组距离的最优算法,并分析时间复杂度。
思想:
1、首先申请两个长度为l + m + n 的数组 t 与 f 数组t用来存储排序后的三个数组 f用来存储当前t数组中的元素位于哪个原始数组中,时间复杂度O(l + m + n)
2、tf数组用来表示 找到三个来自不同数组的元素
3、当tf每次满足时,我们找出其中最大的元素与最小的元素,二者差就是其距离,此时将最小值对应的tf位置为false再继续寻找下一个不同元素
4、每次要记录的元素(左中右)状态是左边,与中间的元素都是同类型元素最右边的,右边元素是同类型元素最左边的
5、三元组距离等最右边的元素减去最左边的元素,然后再把最左边的元素的tf位置为false, 接着从最右边的元素的下一个继续开始执行。
时间复杂度为O(l + m + n)
此方法如有错误,欢迎大家指正,共同学习。
下面程序是匆匆写的,没有进行优化,思想是这样的。
int findMinDist(int a[], int l, int b[], int m, int c[], int n){
int *target = new int[l + m + n];
int *flag = new int[l + m + n]; //0表示a, 1表示b, 2表示c
int f[3] = {false};
//a[l] b[m] c[n]
int ti = l + m + n - 1;
int t = ti;
//-----------------以下是对三个数组进行排序------------------//
while(l && m && n){
if(a[l - 1] >= b[m - 1] && a[l - 1] >= c[n - 1]){
target[t] = a[l - 1]; flag[t] = 0; l--;
}else if(b[m - 1] >= a[l - 1] && b[m - 1] >= c[n - 1]){
target[t] = b[m - 1]; flag[t] = 1; m--;
}else{
target[t] = c[n - 1]; flag[t] = 2; n--;
}
t--;
}
while(m && n){
if(b[m - 1] > c[n - 1]){
target[t] = b[m - 1]; flag[t] = 1; m--;
}else{
target[t] = c[n - 1]; flag[t] = 2; n--;
}
t--;
}
while(n && l){
if(a[l - 1] > c[n - 1]){
target[t] = a[l - 1]; flag[t] = 0; l--;
}else{
target[t] = c[n - 1]; flag[t] = 2; n--;
}
t--;
}
while(l && m){
if(a[l - 1] > b[m - 1]){
target[t] = a[l - 1]; flag[t] = 0; l--;
}else{
target[t] = b[m - 1]; flag[t] = 1; m--;
}
t--;
}
while(l){target[t] = a[l - 1]; flag[t] = 0; l--; t--;}
while(m){target[t] = b[m - 1]; flag[t] = 1; m--; t--;}
while(n){target[t] = c[n - 1]; flag[t] = 2; n--; t--;}
//-----------------------------------------------------------------//
int i = 0, j = 0, k = 0;
int tmp = 0;
int minV = INT_MAX;
while(tmp <= ti){ //i,j,k用来标记三个来自不同数组的元素
if(flag[tmp] == 0){
i = tmp;
}else if(flag[tmp] == 1){
j = tmp;
}else{
k = tmp;
}
f[flag[tmp]] = true; //已经找到的不同元素标记为true
if(f[0] && f[1] && f[2]){
if(i > j && i > k){
if(j < k){ //j k i
minV = min(minV, target[i] - target[j]); f[1] = false;
}else{ //k j i
minV = min(minV, target[i] - target[k]); f[2] = false;
}
}else if(j > i && j > k){
if(i < k){ // i k j
minV = min(minV, target[j] - target[i]); f[0] = false;
}else{ // k i j
minV = min(minV, target[j] - target[k]); f[2] = false;
}
}else{
if(i < j){ // i j k
minV = min(minV, target[k] - target[i]); f[0] = false;
}else{ // j i k
minV = min(minV, target[k] - target[j]); f[1] = false;
}
}
}
tmp++;
}
return minV;
}