問題描述:
已知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