問題如下:
You are given with three sorted arrays ( in ascending order), you are required to find a triplet ( one element from each array) such that distance is minimum.
Distance is defined like this : If a[i], b[j] and c[k] are three elements then distance=max(abs(a[i]-b[j]),abs(a[i]-c[k]),abs(b[j]-c[k]))
Please give a solution in O(n) time complexity
這個演算法有很強的實用性,比如找到3組使用者裡面最相似的3元組,這裡可以把abs替換為一個similarity函數即可。
下面的代碼給出了一個最簡單的Bruce force演算法和一個最佳化演算法。
package com.autofei.algorithm;import java.util.Arrays;public class GoogleMinimumDistance {static void NavieMin(int[] a, int[] b, int[] c) {int min = Integer.MAX_VALUE;String triplet = "";int[] tripletArray = new int[3];for (int i = 0; i < a.length; i++) {for (int j = 0; j < b.length; j++) {for (int k = 0; k < c.length; k++) {tripletArray[0] = Math.abs(a[i] - b[j]);tripletArray[1] = Math.abs(a[i] - c[k]);tripletArray[2] = Math.abs(b[j] - c[k]);Arrays.sort(tripletArray);int distance = tripletArray[2];if (distance < min) {min = distance;triplet = a[i] + "|" + b[j] + "|" + c[k];}}}}System.out.println(triplet + " => " + min);}static void SmartMin(int[] a, int[] b, int[] c) {int min = Integer.MAX_VALUE;String tripletString = "";int[] tripletArray = new int[3];int i = 0;int j = 0;int k = 0;while (i < a.length && j < b.length && k < c.length) {tripletArray[0] = a[i];tripletArray[1] = b[j];tripletArray[2] = c[k];Arrays.sort(tripletArray);int tripletMax = tripletArray[2];int tripletMin = tripletArray[0];int distance = tripletMax - tripletMin;if (distance < min) {min = distance;tripletString = a[i] + "|" + b[j] + "|" + c[k];}if (a[i] == tripletMin) {i++;} else if (b[j] == tripletMin) {j++;} else if (c[k] == tripletMin) {k++;}}System.out.println(tripletString + " => " + min);}public static void main(String[] args) {int[] a = { 4, 10, 15, 28 };int[] b = { 1, 3, 29 };int[] c = { 5, 13, 28 };GoogleMinimumDistance.NavieMin(a, b, c);GoogleMinimumDistance.SmartMin(a, b, c);}}