思路与算法:排序 + 双指针
当我们枚举到恰好等于 target 的 a+b+c 时,可以直接返回 target 作为答案,因为不会有再比这个更接近的值了。枚举 a,b,c 中任意元素并移动指针时,可以直接将其移动到下一个与这次枚举到的不相同的元素,减少枚举的次数。
package com.loo;
import java.util.Arrays;
public class Similar {
public static void main(String[] args) {
int[] arr = new int[]{-1 , 2 , 1 , -4};
System.out.println(similar(arr , 1));
}
public static int similar(int[] arr , int target) {
if (arr == null || arr.length <3) {
System.out.println("maybe arr array is error!!! arr:" + arr + ",len:" + (arr!=null?arr.length:0));
return 0;
}
System.out.println(Arrays.toString(arr));
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
int len = arr.length;
int value = Integer.MAX_VALUE;
for (int i=0;i<len;i++) {
if (i>0 && arr[i]==arr[i-1]) {
// 去掉重复元素
continue;
}
int l = i+1;
int r = len - 1;
while (l<r) {
int sum = arr[i] + arr[l] + arr[r];
// 恰好等于 target 的 a+b+c 时
if (sum == target) {
return target;
}
if (Math.abs(sum - target) < Math.abs(value - target)) {
value = sum;
}
// 如果 a+b+c≥target,那么就将 r 向左移动一个位置,否则左边向右移动一个位置
if (sum > target) {
int r0 = r - 1;
while (l<r0 && arr[r0]==arr[r]) {
r0--;
}
r = r0;
} else {
int l0 = l + 1;
while (l0<r && arr[l0]==arr[l]) {
l0++;
}
l = l0;
}
}
}
return value;
}
}