给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。
示例 1:
输入:nums = [-1,2,1,-4], target = 1 输出:2 解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
示例 2:
输入:nums = [0,0,0], target = 1 输出:0
这一道题该不会是上一题的堂兄弟吧~~~
这题与上一题不同,不同在于上一题的答案可以看作是“静态的”,而这道题的答案可以看作是“动态的”。由于无法准确判断三数之和是大于 target ,还是小于 target ,或是等于 target ,这题的思路相较于上一题会有所出入,但主要的思路还是一致的:排序 + 指针。
直接看代码:
- class Solution {
- public int threeSumClosest(int[] nums, int target) {
- Arrays.sort(nums); // 排序,目的:便于查找遍历
- int a = 100000; // 思考一下,为什么要初始化一个大的值?
- // 三元数的第一个数的指针指向数组的开始,即nums[0],向后遍历nums[i]
- for(int i = 0; i < nums.length; i ++){
- // 向后遍历的过程中,若遇到相同的数字,则循环下一次,跳过当前的循环,否则,继续执行
- if(i > 0 && nums[i] == nums[i - 1]){
- continue;
- }
- // 三元数的第二个数的指针指向数组的 nums[i + 1],向后遍历nums[j],保持第二个数始终在第一个数后面
- // 三元数的第三个数的指针指向数组的末端,即nums[nums.length - 1],向前遍历nums[k]
- int j = i + 1, k = nums.length - 1;
- while(j < k){
- int sum = nums[i] + nums[j] + nums[k]; // 记录三数之和
- // 若三数之和等于 target ,则返回 target
- if(sum == target){
- return target;
- }
- // 取绝对值小的值,将 a 赋值 sum
- if(Math.abs(sum - target) < Math.abs(a - target)){
- a = sum;
- }
- // 如果 sum 大于 target ,则表明正数部分太大,即第三个数 nums[k] 太大,应当向前遍历
- // 如果 sum 小于等于 target ,则表明负数部分太大,此时只需移动 nums[j] 向后遍历即可
- if(sum > target){
- int k0 = k - 1;
- while(j < k0 && nums[k0] == nums[k]){
- k0 --;
- }
- k = k0;
- }else{
- int j0 = j + 1;
- while(j0 < k && nums[j0] == nums[j]){
- j0 ++;
- }
- j = j0;
- }
- }
- }
- return a;
- }
- }
这里解释一下 Math.abs() 用法,通俗的话就是取绝对值,官方一点就是,Math.abs(x):如果 x 是负数(包括 -0),则返回 -x,否则,返回 x。ヾ(•ω•`)o~