16. 最接近的三数之和
题目和第十五题是类似的,解题方式也是一样:先排序,固定一个最小数字,然后再按照寻找target的方式来。
但这题的难点在于,如何证明或者说理解解答方式的正确性。
下面做一个简略的证明:
在我们的每一步固定一个数字后,假设为x,之后的寻找target-x的过程必然覆盖了最小的绝对值,设此时数组为num,左指针为left,右指针为right。
假设我们当前的一次操作是left++,也就意味着当前的情况是num[left]+num[right]<target。
采用反证法,假设因为此时left++操作导致得不到正确答案,又因为我们始终能按正确的寻找有序数组里面的两数和的方式迫近target。
就意味着,最终答案是由当前num[left]参与组成,,那么此时操作right--,但是显然此时num[left]+num[right]<target,num[left]+num[right-1]<=num[left]+num[right]<target,若num[right-1]==num[right],显然又回到了之前状态,所以我们总是假设为以下状态:
于是,如果此时进行right移动,首先不满足[在有序数组里面寻找target]的操作,其次和只会越来越远离target,所以必然能找找答案。
public int threeSumClosest(int[] nums, int target) {
int ans = nums[0]+nums[1]+nums[2];
Arrays.sort(nums);
for (int i = 0; i <= nums.length - 3; i++) {
int left = i + 1, right = nums.length - 1;
while (left < right ) {
int temp = nums[left] + nums[right]+nums[i];
if (Math.abs(ans- target) > Math.abs(temp- target)) {
ans = temp;
}
if (temp < target) {
left++;
} else if (temp > target) {
right--;
} else return target;
}
}
return ans;
}