LeetCode解题 16:3Sum Closest
Problem 16: 3Sum Closest [Medium]
Given an array nums
of n integers and an integer target
, find three integers in nums
such that the sum is closest to target
. Return the sum of the three integers. You may assume that each input would have exactly one solution.
Example:
Given array nums = [-1, 2, 1, -4], and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
来源:LeetCode
解题思路
与15题3Sum类似。
- 使用sort()对数组排序。
- 遍历数组,并在当前数字
nums[i]
的后续数字nums[i+1]
~nums[n-1]
中,使用双指针法寻找与当前数字之和最靠近target
的两个数。
减少执行用时的设计:
- 在N=3时直接返回三数之和。
- 在遍历以及双指针移动过程中跳过重复的数字。
- 遍历数组的当前数字
nums[i]
的三倍与target
的差若大于最小差值(即nums[i]*3 - target > min
),则之后的循环中必不可能出现更靠近target
的结果,可以直接跳出循环。(因为数组已由小到大排序,之后的数字都不小于nums[i]
,之后的三数之和都不小于nums[i]*3
,也就意味着会与target
产生更大的差值,因此可以直接舍去接下来的循环过程。)
排序的时间复杂度O(n log n),遍历数组+双指针过程时间复杂度O(n2),总体时间复杂度O(n2)。
要点:排序
、双指针
Solution (Java)
class Solution {
public int threeSumClosest(int[] nums, int target) {
int N = nums.length;
if(N == 3) return nums[0] + nums[1] + nums[2];
Arrays.sort(nums);
int min = Integer.MAX_VALUE;
int result = 0;
int last = nums[0];
int left, right, temp, sum;
for(int i = 0; i < N-2; i++){
if(nums[i]*3 - target > min) break;
if(nums[i] == last && i > 0) continue;
last = nums[i];
left = i+1;
right = N-1;
while(left < right){
sum = nums[i] + nums[left] + nums[right];
if(sum - target == 0){
return target;
}
else if(sum - target > 0){
if(sum - target < min){
min = sum - target;
result = sum;
}
temp = nums[right];
while(--right > left && nums[right] == temp);
}
else{
if(target - sum < min){
min = target - sum;
result = sum;
}
temp = nums[left];
while(++left < right && nums[left] == temp);
}
}
}
return result;
}
}