问题描述:
已知3个升序整数数组a[l]、b[m]、c[n]。请在3个数组中各找一个元素,使得组成的三元组距离最小。
三元组距离的定义是:假设a[i]、b[j]和c[k]是一个三元组,那么距离为Distance=max(|a[i]-b[j]|,|a[i]-c[k]|,|b[j]-c[k]|),请设计一个求最小三元组距离的最优算法。
方法一:
暴力法。分别遍历3个数组中的元素,分别求出它们的距离,然后寻找最小距离。时间复杂度:O(l*m*n)。
方法一代码如下:
package com.haobi;
public class Test32 {
public static void main(String[] args) {
int a[] = {3,4,5,7};
int b[] = {10,12,14,16,17};
int c[] = {20,21,23,24,37,38};
System.out.println(minDistance(a,b,c));
}
public static int minDistance(int[]a, int[]b, int[]c) {
int aLen = a.length;
int bLen = b.length;
int cLen = c.length;
int minDist = max(Math.abs(a[0]-b[0]),Math.abs(b[0]-c[0]),Math.abs(a[0]-c[0]));
int dist = 0;
for(int i=0;i<aLen;i++) {
for(int j=0;j<bLen;j++) {
for(int k=0;k<cLen;k++) {
//求距离
dist = max(Math.abs(a[i]-b[j]),Math.abs(b[j]-c[k]),Math.abs(a[i]-c[k]));
//记录最小距离
if(dist < minDist) {
minDist = dist;
}
}
}
}
return minDist;
}
public static int max(int a, int b, int c) {
int max = a<b? b:a;
max = max<c? c:max;
return max;
}
}
程序输出结果如下:
13
方法二:
最小距离法。假设当前遍历到这3个数组中的元素分别为ai、bi、ci,并且ai<bi<ci,此时它们的距离肯定为Di = ci - ai,那么可以分为如下3种情况讨论:
(1)如果接下来求ai、bi、ci+1 的距离,那么由于ci+1 > ci,此时Di+1 = ci+1 - ai,因此Di+1 > Di,因此Di+1不可能为最小距离。
(2)如果接下来求ai、bi+1、ci 的距离,分为两种清理:①、如果bi+1 > ci,那么此时它们的距离为Di+1 = bi+1 - ai,显然Di+1 > Di,因此Di+1不可能为最小距离;②、如果bi+1 <= ci,此时它们的距离仍然为Di = ci - ai;
(3)如果接下来求ai+1、bi、ci 的距离,如果ai+1 < |ci - ai| + ci,此时它们的距离Di+1 = ci - ai+1,显然Di+1 < Di,因此Di+1可能是最小的距离。
综上所述,从3个数组的第一个元素开始,先求出它们的距离minDist,接着找出这3个数中最小数对应的数组,只对这个数组的下标往后移一个位置,接着求3个数组中当前元素的距离,若比minDist小,则把当前距离赋值给minDist,以此类推,直至遍历完其中一个数组。时间复杂度:O(l+m+n)。
方法二代码如下:
package com.haobi;
public class Test33 {
public static void main(String[] args) {
int a[] = {3,4,5,7};
int b[] = {10,12,14,16,17};
int c[] = {20,21,23,24,37,38};
System.out.println(minDistance(a,b,c));
}
public static int minDistance(int[]a, int[]b, int[]c) {
int aLen = a.length;
int bLen = b.length;
int cLen = c.length;
int curDist = 0;
int min = 0;//当前最小值
int minDist = Integer.MAX_VALUE;
int i = 0;//数组a的下标
int j = 0;//数组b的下标
int k = 0;//数组c的下标
while(true) {
//求距离
curDist = max(Math.abs(a[i]-b[j]),Math.abs(b[j]-c[k]),Math.abs(a[i]-c[k]));
if(curDist < minDist) {
minDist = curDist;
}
//找出当前遍历到3个数组中的最小值
min = min(a[i],b[j],c[k]);
if(min == a[i]) {
if(++i >= aLen) {
break;
}
}else if(min == b[j]) {
if(++j >= bLen) {
break;
}
}else if(min == c[k]) {
if(++k >= cLen) {
break;
}
}
}
return minDist;
}
public static int min(int a, int b, int c) {
int min = a<b? a:b;
min = min<c? min:c;
return min;
}
public static int max(int a, int b, int c) {
int max = a<b? b:a;
max = max<c? c:max;
return max;
}
}
程序输出结果如下:
13