【温故知新】`16.最接近的三数之和` 排序+双指针实现

332 阅读1分钟

image.png

题目描述

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

 

示例:

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

提示:

3 <= nums.length <= 10^3 -10^3 <= nums[i] <= 10^3 -10^4 <= target <= 10^4

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/3s… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

思路1:排序+双指针实现

  • 对nums进行排序确保nums[left]<=nums[right];
  • 每次for循环确认一个基点nums[i]
  • 每次for循环确认基于nums[i]的最小接近值
    • 如果sum===target 则直接返回sum,提前结束;
    • 如果sum<target ,则 left++;否则right--;
    • 如果(Math.abs(target-sum)<Math.abs(target-closeRes))
      • 更新接近值:closeRes=sum;

时空复杂度

  • 时间复杂度:O(N^2),其中 N是数组 nums 的长度。我们首先需要O(NlogN) 的时间对数组进行排序,随后在枚举的过程中,使用一重循环 O(N) 枚举 a,双指针 O(N) 枚举 b 和 c,故一共是 O(N^2)

  • 空间复杂度:O(log N)。排序需要使用 O(logN) 的空间。然而我们修改了输入的数组 nums,在实际情况下不一定允许,因此也可以看成使用了一个额外的数组存储了 nums 的副本并进行排序,此时空间复杂度为 O(N)。

代码

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var threeSumClosest = function(nums, target) {
  // 排序 + 双指针 
   // 1、排序
  nums.sort((a,b)=>{return a-b});
  // 2、双指针
  let  closeRes=nums[0]+nums[1]+nums[2]
  let len=nums.length;
  for(let i=0;i<len;i++){
      // 将每一个元素作为一个基准值,使用双指针进行遍历计算最接近target的结果;
      let left=i+1;
      let right=len-1
      while(left<right){
          let sum=nums[i]+nums[left]+nums[right]
           // 特殊情况优先处理,提前结束
          if(sum===target){
              return target;

          }else if(sum<target){
              left++
          }else if(sum>target){
              right--
          }
          // 一次遍历结束后,比较sum,进行closeRes更新;
         if(Math.abs(target-sum)<Math.abs(target-closeRes)){
             closeRes=sum
         }
      }// end of while 
  }// end of for 
    return closeRes;

};