LeetCode16.最接近的三数之和
各位朋友们大家好呀,我是你的老朋友冢狐,今天我们来看一道LeetCode上的中等难度的题目——最接近的三数之和问题。希望看完这篇文章后能给各位带来一些收获。
题目:
首先我们先来看一下题目的描述:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J1j4JLzT-1593154112609)(https://raw.githubusercontent.com/iszhonghu/Picture-bed/master/img/20200626110631.png)]
分析
对于这个问题我们先从简单的场景来分析:
只找一个数
那最简单的场景无非是找最接近的一数之和,那么我们只需要维护一个变量:best。best记录这个目前的最佳值,遇到更合适的就替换这个best直到遍历完整个数组。
找两个数的和
再复杂一点就是找最接近的两个数的和。最简单的想法就是化简为上一种情况,将目标值先减去一个值,然后在去寻找剩下的,但是这样由于嵌套for循环导致时间复杂度不是很友好,存在优化的空间。
现在问题来了:到底优化的空间在哪里?如何将这一部分空间节约出来?
上述方法存在的问题就是,当我们第一个已经比目标值小的情况下在去和一个负值相加就更不可能是我们的目标,再往下扩展一步就是,当我们a+b已经小于目标值的情景下,再去找一个比b小的值来和a相加就完全没有必要了。
- 有序数组加双指针:
- 那我们先将数组进行排序,然后就得到了一个有序的数组
- 然后left和right两个指针分别指向第一个和最后一个,将其相加得到sum,然后比较best和sum那个更接近目标值
- 然后判断sum比目标值大还是小,大的话右指针左移,小的话左指针右移。
找三个数的和
既然有了前两次的经验,那我们就转化为找两数之和,即先找一个固定值,然后双指针。
代码实现
public int threeSumClosest(int[] nums, int target) {
// 先将数组排序以便和后续双指针运算
Arrays.sort(nums);
int len = nums.length;
// 赋值默认初始值,
int best = nums[0] + nums[1] + nums[2];
int sum = 0;
// 固定a找b和c
for (int a = 0; a < len; a++) {
// 为了防止重复查找 b=a+1;
int b = a + 1;
int c = len - 1;
while (b < c) {
sum = nums[a] + nums[b] + nums[c];
if (sum == target) {
return sum;
}
// 判断是否需要更新最佳值
if (Math.abs(sum - target) < Math.abs(best - target)) {
best = sum;
}
// 判断双指针哪一个需要移动
if (sum > target) {
c--;
} else {
b++;
}
}
}
return best;
}
最后
- 如果觉得看完有收获,希望能给我点个赞,这将会是我更新的最大动力,感谢各位的支持
- 欢迎各位关注我的公众号【java冢狐】,专注于java和计算机基础知识,保证让你看完有所收获,不信你打我
- 如果看完有不同的意见或者建议,欢迎多多评论一起交流。感谢各位的支持以及厚爱。