【中等】题解力扣16:最接近的三数之和
题目详情
给你一个长度为n
的整数数组 nums
和一个目标值 target
,请你从num
中选出三个整数,使它们的和与 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 最接近的和是 0(0 + 0 + 0 = 0)。
提示:
3 <= nums.length <= 1000
-1000 <= nums[i] <= 1000
-10^4 <= target <= 10^4
解题思路
- 排序数组:首先对数组进行排序,便于使用双指针技巧。
- 初始化最接近和:以数组的前三个元素之和作为初始值。
- 外层循环优化:
- 计算当前固定值
nums[i]
的最小可能三数之和(nums[i] + nums[i+1] + nums[i+2]
)。若该值大于target
,则后续所有组合都会更大,此时更新最接近和后直接返回。 - 计算当前固定值
nums[i]
的最大可能三数之和(nums[i] + nums[n-2] + nums[n-1]
)。若该值小于target
,则当前i
的所有组合都会更小,更新最接近和后跳过当前i
。
- 双指针搜索:
- 内层使用双指针
left
和right
搜索剩余两个数。 - 若三数之和等于
target
,直接返回。 - 否则更新最接近和,并根据当前和与
target
的大小关系移动指针。
- 跳过重复元素:移动指针时跳过重复值,避免重复计算。
代码实现(Java版)
import java.util.Arrays;class Solution {public int threeSumClosest(int[] nums, int target) {Arrays.sort(nums);int n = nums.length;int closestSum = nums[0] + nums[1] + nums[2];for (int i = 0; i < n - 2; i++) {if (i > 0 && nums[i] == nums[i - 1]) continue;// 最小三数之和优化int minSum = nums[i] + nums[i + 1] + nums[i + 2];if (minSum > target) {if (minSum - target < Math.abs(closestSum - target)) {closestSum = minSum;}break;}// 最大三数之和优化int maxSum = nums[i] + nums[n - 2] + nums[n - 1];if (maxSum < target) {if (target - maxSum < Math.abs(closestSum - target)) {closestSum = maxSum;}continue;}int left = i + 1, right = n - 1;while (left < right) {int sum = nums[i] + nums[left] + nums[right];if (sum == target) return target;if (Math.abs(sum - target) < Math.abs(closestSum - target)) {closestSum = sum;}if (sum < target) {left++;while (left < right && nums[left] == nums[left - 1]) left++;} else {right--;while (left < right && nums[right] == nums[right + 1]) right--;}}}return closestSum;}
}
代码说明
- 排序:
Arrays.sort(nums)
将数组排序,为双指针法奠定基础。 - 外层循环优化:
- 最小和优化:当
nums[i] + nums[i+1] + nums[i+2] > target
时,后续所有组合的和都会更大,此时更新最接近和后直接结束循环。 - 最大和优化:当
nums[i] + nums[n-2] + nums[n-1] < target
时,当前i
的所有组合和都小于target
,更新最接近和后跳过当前i
。
- 双指针搜索:
- 固定
nums[i]
,使用双指针在[i+1, n-1]
区间搜索。 - 当三数之和等于
target
时直接返回。 - 否则更新最接近和,并根据当前和与
target
的关系移动指针。
- 跳过重复值:移动指针时跳过重复元素,避免重复计算相同组合。
- 返回结果:循环结束后返回最接近的和
closestSum
。 - 该算法通过提前终止无效循环(最小和大于
target
或最大和小于target
的情况),显著减少计算量。时间复杂度为 O(n²),空间复杂度为 O(1)。