题目

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

示例1

  1. 输入:nums = [-1,2,1,-4], target = 1
  2. 输出:2
  3. 解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2)

实现

首先可以发现该题与Leetcode第15题“三数之和”类似(解题笔记如下)。
语雀内容
因此也可以用排序+双指针的思路去解决。

思路1 排序+双指针

类似的,第一重循环遍历第一个数a,剩下两个数b和c的和要最接近target-a。
接着如果数组中的数字都是乱序的,那我们必须使用两重循环来枚举所有可能。因此我们需要对数组进行排序,这样第二重循环就可以从a所在的位置到数组的尾部之间(即[a+1, size))枚举。
然后与第15题一样使用双指针替代第三重循环,降低复杂度。并用第11题“盛最多水的容器”的思路来移动双指针,即根据b,c与target关系决定移动b还是c的指针:

  • 当b+c>target-a时,往左移动c的指针
  • 当b+c<target-a时,往右移动b的指针

    1. class Solution {
    2. public:
    3. int threeSumClosest(vector<int>& nums, int target) {
    4. sort(nums.begin(), nums.end());
    5. int n = nums.size();
    6. int best = 1e7;
    7. for(int a = 0; a<n; a++){
    8. if(a>0 && nums[a]==nums[a-1]){
    9. continue;
    10. }
    11. int b = a+1, c = n-1;
    12. while(b<c){
    13. int sum = nums[a] + nums[b] + nums[c];
    14. if(sum == target){
    15. return sum;
    16. }
    17. if(abs(sum-target) < abs(best-target)){
    18. best = sum;
    19. }
    20. if(sum < target){
    21. // 移动b指针到下一个不相等的数
    22. // 这里b+1<c是防止数组为[1,1,1,1]时会超过数组边界
    23. while(b+1<c && nums[b]==nums[b+1]){
    24. b++;
    25. }
    26. b++;
    27. } else{
    28. // 移动c指针到下一个不相等的数
    29. while(c-1>b && nums[c]==nums[c-1]){
    30. c--;
    31. }
    32. c--;
    33. }
    34. }
    35. }
    36. return best;
    37. }
    38. };