题意描述:
给定一个包括 n
个整数的数组 nums
和 一个目标值 target
。找出 nums
中的三个整数,使得它们的和与 target
最接近。返回这三个数的和。假定每组输入只存在唯一答案。
示例:
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
解题思路:
Alice: 三重循环应该不行吧,会超时吧。
Bob: 不知道哦,我们可以试试看,而且应该能优化一些的。
Alice: 三数之和与 target
最接近的时候,两者的差值应该就是 0
,这一点可以直接优化。
Bob: Amazing ,三重循环加一点优化居然可以啊。
Alice: 排序 + 双指针应该也可以。就是三数之和那题一样。
Bob: 应该是可以的,外层循环遍历三元组中最小的元素,然后用双指针从两个方向把 三元组之和 逼近 target 目标值。
Alice: 对对对,这样可以减少 搜索 三元组 的次数,只需要每次移动双指针的时候检测 三元组的值就行了。
Bob:
代码:
Python 方法一: 三重循环 + 一点点优化,竟然也能过,Amazing !
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
minValue = 2147483647
for x in range(len(nums)):
for y in range(x+1, len(nums)):
for z in range(y+1, len(nums)):
tmp = abs(nums[x] + nums[y] + nums[z] - target)
if tmp < minValue:
minValue = tmp
ret = nums[x] + nums[y] + nums[z]
if minValue == 0:
return ret
return ret
Java 方法一: 三重循环,竟然通过了。Amazing !
class Solution {
public int threeSumClosest(int[] nums, int target) {
int tmp = 0;
int ans = 0;
int minValue = 2147483647;
for(int i=0; i<nums.length; ++i){
for(int j=i+1; j<nums.length; ++j){
for(int k=j+1; k<nums.length; ++k){
tmp = abs(nums[i] + nums[j] + nums[k] - target);
if(tmp < minValue){
minValue = tmp;
ans = nums[i] + nums[j] + nums[k];
}
if(minValue == 0){
return ans;
}
}
}
}
return ans;
}
public int abs(int a){
if(a < 0){
a *= -1;
}
return a;
}
}
Python 方法二: 排序 + 双指针 ,通过。
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
ans = 0
minValue = 2147483647
for x in range(len(nums)): # 假设最外层遍历的是 三元组 中最小的元素
left = x + 1
right = len(nums) - 1
tmp = 0
while left < right:
tmp = nums[x] + nums[left] + nums[right]
if tmp == target:
return target
elif tmp > target:
right -= 1
else:
left += 1
if abs(tmp - target) < minValue:
minValue = abs(tmp - target)
ans = tmp
return ans
Java 方法二: 排序 + 双指针。
class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int ans = 0;
int left = 0;
int right = 0;
int tmpSum = 0;
int tmpDiff = 0;
int minValue = 2147483647;
for(int i=0; i<nums.length; ++i){
left = i + 1;
right = nums.length - 1;
while(left < right){
tmpSum = nums[i] + nums[left] + nums[right];
if(tmpSum == target){
return target;
}else if(tmpSum < target){
left += 1;
}else{
right -= 1;
}
tmpDiff = abs(tmpSum - target);
if(tmpDiff < minValue){
minValue = tmpDiff;
ans = tmpSum;
}
}
}
return ans;
}
public int abs(int a){
if(a < 0){
a *= -1;
}
return a;
}
}
易错点:
[-26,84,-85,2,99,42,-28,16,-97,-59,64,-67,-30,18,-15,-11,-60,-79,41,-29,49,-33,21,-8,-73,6,-31,31,-23,82,-34,12,86,38,-4,99,4,63,-13,-42,-4,89,88,-30,0,15,37,-95,-85,15,66,8,43,95,-76,75,-16,48,15,-82,56,83,91,81,-76,-29,7,-77,-42,39,-73,29,43,-60,21,-5,-3,1,32,34,-77,49,68,-1,-63,93,-20,-57,-65,53,23,96,79,87,-12,-18,51,39,-24,27,13,-55,-6,28,95,91,-71,77,49,-26,-17,-83,43,-86,28,20,64,-6,53,40,81,-30,-83,67,-3,25,37,54,95,14,84,-96,76,15,35,41,-86,33,10,-32,59,100,30,-9,58,-80,23,20,43,93,58,-26,37,44,-24,27,99,-46,-80,-85,-44,-45,-72,-32,33,-24,91,-67,75,-40,52,49,94,-10,82,-76,-92,58,18,-43,47,-75,-17,-30,-17,-57,37,51,-32,69,54,-71,-98,-74,-17,99,84,-67,80,-24,-100,98,19,99,-7,-98,-43,73,-97,-21,96,-44,59]
-186
-186
总结: