题目:
给定一个包括 n 个整数的数组 nums
和 一个目标值 target
。找出 nums
中的三个整数,使得它们的和与 target
最接近。返回这三个数的和。假定每组输入只存在唯一答案。
这是一道数组题,并和15题三数之和十分接近,因此采用的算法思想也十分接近,都是三指针遍历,分别为i指向最小位,j为中间位,k为最大位。遍历的情况可分为三种:
1.nums[i]+nums[j]+nums[k]==target,由于答案唯一,此即为最接近答案,直接return。
2.nums[i]+nums[j]+nums[k]>target,我们的目的时找到离target最近的三个数,因此需要使得nums[i]+nums[j]+nums[k]-target更加贴近0,而此时三数之和与target之差已经大于0,所以要降低三个数的和,于是需要将k向左拨,k--;
3. 2.nums[i]+nums[j]+nums[k]<target,同理,我们要将三数之和与target的差更贴近0,所以要加大三数的和,于是需要将j右拨,j++;
和15题一样,要考虑重复的问题,所以需要加上邻位判定。在此就不赘述。
贴上代码。
class Solution { public int threeSumClosest(int[] nums, int target) { int i; int j; int k; int result=nums[0]+nums[1]+nums[2];//初始值 int min=Math.abs(nums[0]+nums[1]+nums[2]-target);//初始值 Arrays.sort(nums); for(i=0;i<nums.length-2;){ j=i+1; k=nums.length-1; while(j<k){ if(nums[i]+nums[j]+nums[k]==target){ return nums[i]+nums[j]+nums[k]; } else if(nums[i]+nums[j]+nums[k]>target){//a+b+c-target>0情况,要将k左拨,才能更贴近0 if(Math.abs(nums[i]+nums[j]+nums[k]-target)<min) { min=Math.abs(nums[i]+nums[j]+nums[k]-target);//记录最小值 result=nums[i]+nums[j]+nums[k]; } k--; while(j<k&&nums[k]==nums[k+1]){ k--; } } else if(nums[i]+nums[j]+nums[k]<target){//a+b+c-target<0情况,要将j右拨,才能更贴近0 if(Math.abs(nums[i]+nums[j]+nums[k]-target)<min) { min=Math.abs(nums[i]+nums[j]+nums[k]-target);//记录最小值 result=nums[i]+nums[j]+nums[k]; } j++; while(j<k&&nums[j]==nums[j-1]){ j++; } } } i++; while(i<nums.length-2&&nums[i]==nums[i-1]){ i++; } } return result; } }
提交结果如下:
结论:排名更靠前的提交记录基本用到类似的思想,不过增加了更多情况的出口,减少了时间复杂度,但大体来说都是一样的。