题目描述
给定一个包括 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;
};