思路:
与上题差不多,只是不能再用系统自带的二分法,要自己写一个。
package Level3;
import java.util.Arrays;
/**
* 3Sum Closest
*
* Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
*/
public class S16 {
public static void main(String[] args) {
int[] num = {-1,2,1,-4};
System.out.println(threeSumClosest(num, 1));
}
public static int threeSumClosest(int[] num, int target) {
int sum = 0;
int diff = Integer.MAX_VALUE;
Arrays.sort(num);
for (int i = 0; i < num.length - 1; i++) { // 前指针向后
for (int j = num.length - 1; j > i+1; j--) { // 后指针向前
int remain = target - (num[i] + num[j]);
int third = bsearch(num, i + 1, j, remain);
int tmp = num[i] + num[third] + num[j];
if(Math.abs(tmp-target) < diff){ // 保存最小不同的数
diff = Math.abs(tmp-target);
sum = tmp;
}
}
}
return sum;
}
// 修改版二分法
public static int bsearch(int[] num, int low, int high, int key){
int mid = low + (high-low)/2;
while(low < high){ // low不能与high相等!
mid = low + (high-low)/2;
if(num[mid] == key){
return mid;
}else if(key < num[mid]){
high = mid-1;
}else{
low = mid+1;
}
}
return mid;
}
}
Rewrite:
public int threeSumClosest(int[] num, int target) {
if (num.length<3) { // if less than three items then return 0
return Integer.MAX_VALUE;
}
Arrays.sort(num);
int res = num[0]+num[1]+num[2];
for (int i=0; i<num.length-2; ++i) {
if (i>0 && num[i]==num[i-1]) continue;
int start = i+1, end = num.length-1;
while (start<end) {
int sum = num[i] + num[start] + num[end];
if (Math.abs(sum-target) < Math.abs(res-target)) {
res = sum;
}
if (sum == target) {
return res;
} else if (sum < target) {
start++;
} else {
end--;
}
}//end-while
}
return res;
}
public class Solution {
public int threeSumClosest(int[] num, int target) {
Arrays.sort(num);
int diff = Integer.MAX_VALUE;
int closetSum = 0;
for(int i=0; i<=num.length-3; i++) {
int left = i+1;
int right = num.length-1;
while(left < right) {
int sum = num[i]+num[left]+num[right];
if(Math.abs(sum-target) < diff) {
diff = Math.abs(sum-target);
closetSum = sum;
}
if(sum == target) {
return sum;
} else if(sum < target) {
left++;
} else {
right--;
}
}
}
return closetSum;
}
}