先贴个题目和答案。
/**
* 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 N16_3Sum_Closest {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
if(nums == null || nums.length == 0)
{
return 0;
}
int closest = nums[0] + nums[1] + nums[2];
int diff = Integer.MAX_VALUE;
for(int i = 0 ; i < nums.length - 2; i++)
{
int left = i + 1;
int right = nums.length - 1;
while(left < right )
{
int sum = nums[i] + nums[left] + nums[right];
//如果总和大于target,那么左边越小越好,所以减小right
if(sum > target)
{
if(sum - target < diff )
{
//到达了这个点
diff = sum - target;
closest = sum;
}
right -- ;
}
else if(sum < target){
// System.out.println("left = " + left);
// System.out.println("right = " + right);
if( target - sum < diff)
{
diff = target - sum;
closest = sum;
}
left ++ ;
}
else{
return target;
}
}
}
return closest;
}
public static void main(String[] args) {
int[] test = {
0,0,0
};
int[] test2 = {
0,2,1,-3
};// target = 1;
int[] test3 ={
1,2,4,8,16,32,64,128
};//target = 84;
int[] test4 = {
87,6,-100,-19,
10,-8,-58,56,14,-1,-42,-45,-17,10,
20,-4,13,-17,0,11,-44,65,74,-48,30,-91,13,-53,76,-69,-19,
-69,16,78,-56,27,41,67,-79,-2,30,-13,-60,39,95,64,
-12,45,-52,45,-44,73,97,100,-19,-16,-26,58,-61,53,70,
1,-83,11,-35,-7,61,30,17,98,29,52,75,-73,-73,-23,-75,91,
3,-57,91,50,42,74,-7,62,17,-91,55,94,-21,-36,73,19,-61,
-82,73,1,-10,-40,11,54,-81,20,40,-29,96,89,57,10,-16,-34,
-56,69,76,49,76,82,80,58,-47,12,17,77,-75,-24,11,-45,60,
65,55,-89,49,-19,4
};//target = - 275
int[] test5 = {
0,1,2
};//target = 0 检查边界条件thisClosest是否正确初始化
int[] test6 = {
0,0,0
};//target = 1
int[] test7 = {
-100,-90,-90,-88,-70,0,10,22,22,22,33,34
};//target = -260
System.out.println("closest = " + new N16_3Sum_Closest().threeSumClosest(test4,-275));
Arrays.sort(test4);
for(int i = 0; i < test4.length ; i ++)
{
System.out.print(test4[i] + ",");
if(i % 10 == 0)
{
System.out.println();
}
}
}
}
题意是让你从给定的数组里找出三个数,要求这三个数的和要和给定的一个target最接近。要返回这三个数的和。
这道题用从15题学来的遍历方法,避免超时。这道题花了我很长时间,一开始走偏了道路。我试图从数学的角度来做这个题,做了如下的图:
错误是从这里开始的——试图寻找target这个点或者是target左右的两个点。于是就陷入了混乱中。最终通过看discuss才找到了方向:全部遍历一遍,而不是试图通过这个图像来找到答案。此方法的缺陷在于,对于target = 0,答案1和-1都是成立的,但只能找出一个来。
现在,如果要通过这个图像来寻找答案的话,首先需要找到所有的和,记下他们中大于target的最小的,记下小于target中的最大的。然后让他们进行比较即可找到,此方法可以找出两个答案来。