一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第26天,点击查看活动详情。
今天周四,快乐的是快要放假了,死亡的是今晚要上线我的功能
最接近的三数之和
该题出自力扣的16题 - 最接近的三数之和【中等题】
审题
给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。
- 题意很简单,就是给出一个数组,找出数组中存在的三个数,相加总和最接近目标target的总和
- 对数组进行排序后,可以更直观地了解到接近的数
- 解法: 排序 + 双指针
- 对数组进行排序,排序是为了更为直观地找到接近的数,不需要全局搜索
- 双指针,其实也可以使用三指针,直接指向目标数
- 初始总和等于 最小的三个数,也就是索引下标的0、1、2
- 遍历整个数组,在内部进行while循环获取最小值,并且每次循环继续
- 每一次枚举的过程中,尝试从边界的left元素和right元素,根据与目标值的关系,选择左元素右移还是右元素左移。
- 本来如果使用暴力循环的话,就是三重for循环,那就是时间复杂度为O(n^3),但是如果使用排序后的双指针方法,时间复杂度为O(n^2)
- 其中的一些小巧妙,就是如果 最小值等于目标值的时候,则可以剪枝,直接返回即可
- 空间复杂度为O(lgn),因为排序的内部使用了副本存储
编码
class Solution {
public int threeSumClosest(int[] nums, int target) {
//排序 + 双指针
Arrays.sort(nums);
int min = nums[0] + nums[1] + nums[2];
for (int i = 0;i<nums.length -2;i++){
int l = i +1,r = nums.length -1;
while (l<r){
int threeSum = nums[i] + nums[l] + nums[r];
if (Math.abs(threeSum - target) < Math.abs(min - target)){
min = threeSum;
}
if (threeSum > target){
r--;
}else if (threeSum<target){
l ++;
}else {
return target;
}
}
}
return min;
}
}