LeetCode16. 最接近的三数之和
题目描述
/**
*
* 给定一个包括 n 个整数的数组 nums 和 一个目标值 target。
* 找出 nums 中的三个整数,使得它们的和与 target 最接近。
* 返回这三个数的和。假定每组输入只存在唯一答案。
*
*/
思路分析
- 使用排序 + 双指针的思路
- 排序的目的,主要是为了双指针的移动而提供条件,双指针能大大减少程序运行花费的时间
- 使用双指针,只需要从左到右遍历一次数组中元素,使用第一个指针每次都指向此次循环开始的下一个元素,使用另一个指针指向倒数第一个元素
- 外层循环每次遍历数组元素,然后通过双指针,每次判断当前外层循环的三个数组元素之和的最小值,即拿到当前指针对应的数组元素的三个值,如果他们的和大于target则只需要移动后端指针,否则只需要移动左端指针即可,当然如果三个数的和等于target,则直接返回,当左右指针相等时,说明一次外层循环遍历结束,则开始下一次外层循环
- 比较每此获取的三个数的和与target的绝对值的最小值,若是最小的,则重置
- 详细代码见下
源码及分析
// 思路分析
//1. 定义三个指针分别指向数组元素的下标
//2. 从左到右依次遍历,第一个指针控制外层循环,从第一个到最后一个,
// 第二个和第三个指针分别指向第一个指针右侧元素的最左端和最右端
//3. 依次比较每次循环得到的三个数的和与target的大小关系,找到最接近的三个数,并记录
public int threeSumClosest(int[] nums, int target) {
//数组长度
int len = nums.length;
//数据校验
if (nums == null || len < 3) {
throw new RuntimeException("数据输入有误~~");
}
//对数组元素进行排序
Arrays.sort(nums);
//定义三个指针
int first = 0,second = first + 1, third = len - 1;
//定义sum保存三数的和
int sum = nums[first] + nums[second] + nums[third];
//定义minSum保存最小的和
int minSum = sum;
//定义min保存最接近的值
int min = Math.abs(sum - target);
//外层循环遍历一次数组
for (; first < len - 2; first++) {
//定义其他两个指针指向first右侧数组的左右
second = first + 1;
third = len - 1;
//使用双指针遍历
while (true) {
//否则寻找最接近target的三个数
sum = nums[first] + nums[second] + nums[third];
int temp = Math.abs(sum - target);
//如果新的三个数的和更接近target
if (min > temp){
min = temp;
minSum = sum;
}
//判断并移动指针
if (sum == target) {
return target;
} else if (sum > target) {
third--;
} else {
second++;
}
//判断循环结束的条件
if (second == third) {
break;
}
}
}
return minSum;
}