题目描述(中等难度)
给定一个包括 n
个整数的数组 nums
和 一个目标值 target
。找出 nums
中的三个整数,使得它们的和与 target
最接近。返回这三个数的和。假定每组输入只存在唯一答案。
解法一 暴力解法
写三个循环遍历,求出三个数的和和目标值进行比较,选取差值最小的即可。
Java
public class _3_Sum_Closest {
public static int threeSumClosest(int[] nums,int target) {
int res=Integer.MAX_VALUE;
int sum=0;
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++) {
if(Math.abs(nums[i]+nums[j]+nums[k]-target)<res) {
sum=nums[i]+nums[j]+nums[k];
res=Math.abs(sum-target);
}
}
}
}
return sum;
}
public static void main(String args[]) {
int target=1;
int[] nums= {-1,2,1,-4,1};
int ans=threeSumClosest(nums,target);
System.out.println(ans);
}
}
时间复杂度:O(n³)。
空间复杂度:O(1),常数个。
Python
class Solution(object):
def threeSumClosest(self, nums, target):
res=sys.maxsize
sum = 0
for i in range(len(nums)):
for j in range(i+1,len(nums)):
for k in range(j+1,len(nums)):
if(abs(nums[i]+nums[j]+nums[k]-target)<res):
sum=nums[i]+nums[j]+nums[k]
res=abs(sum-target)
return sum
可以看出,python的执行效率整体偏低。
解法二
受到上一题的启发。我们完全可以先将数组排序,然后先固定一个数字,然后利用头尾两个指针进行遍历,降低一个 O(n)的时间复杂度。如果 sum 大于 target 就减小右指针,反之,就增加左指针。
Java
class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int res = Integer.MAX_VALUE;
int sum = 0;
for(int i=0;i<nums.length;i++){
int l = i+1, r = nums.length-1;
while(l < r) {
if(Math.abs(nums[i]+nums[l]+nums[r]-target)<res) {
sum=nums[i]+nums[l]+nums[r];
res=Math.abs(sum-target);
}
if(nums[i]+nums[l]+nums[r]>target){
r--;
}else{
l++;
}
}
}
return sum;
}
}
时间复杂度:如果是快速排序的
O
(
log
n
)
O\left(\log _{n}\right)
O(logn)再加上 O(n²),所以就是 O(n²)。
空间复杂度:O(1)。
class Solution(object):
def threeSumClosest(self, nums, target):
nums.sort()
res = sys.maxsize
sum = 0
for i in range(len(nums)):
l = i+1
r = len(nums)-1
while(l < r):
if(abs(nums[i]+nums[l]+nums[r]-target)<res):
sum=nums[i]+nums[l]+nums[r]
res=abs(sum-target)
if(nums[i]+nums[l]+nums[r]>target):
r-=1
else:
l+=1
return sum
参考文献
- https://zhuanlan.zhihu.com/p/56182884