题目描述
暴力法求解
class Solution {
public int threeSumClosest(int[] nums, int target) {
if(nums==null||nums.length<3)
return 0;
int sum = Integer.MAX_VALUE;//记录和
int dlter = Integer.MAX_VALUE;//记录间隔
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++){
int res = nums[i]+nums[j]+nums[k];
int dlter_before = res-target;
if(Math.abs(dlter_before)<Math.abs(dlter)){
dlter = dlter_before;
sum = res;
}
}
}
}
return sum;
}
}
效率感人。
着手优化一:
class Solution {
public int threeSumClosest(int[] nums, int target) {
if(nums==null||nums.length<3)
return 0;
if(nums.length==3){
return nums[0]+nums[1]+nums[2];
}
Arrays.sort(nums);
int sum = Integer.MAX_VALUE;//记录和
int dlter = Integer.MAX_VALUE;//记录间隔
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
if((sum-target)==0){
return sum;
}
// if(sum!=Integer.MAX_VALUE&&(nums[i]+nums[j]>target)&&nums[j]>=0){
// if(j+1<nums.length)
// sum = nums[i]+nums[j]+nums[j+1];
// return sum;
// }
int res1 = nums[i]+nums[j];
if(res1>target&&nums[j]>=0&&sum!=Integer.MAX_VALUE){
//无需枚举k
break;
}
for(int k=j+1;k<nums.length;k++){
int res = nums[i]+nums[j]+nums[k];
int dlter_before = res-target;
if(Math.abs(dlter_before)<Math.abs(dlter)){
dlter = dlter_before;
sum = res;
if(dlter_before>0)//k是升序的,大于0则后面的都不需要枚举了。
break;
}
}
}
}
return sum;
}
}
着手优化2:双指针
原则上还是三层循环。我们必须将一层循环去除。想着可以使用双指针来优化该类问题。于是开始了自己的思考:
双指针一般是利用了数据的规律进行的。
class Solution {
public int threeSumClosest(int[] nums, int target) {
if(nums==null||nums.length<3)
return 0;
if(nums.length==3){
return nums[0]+nums[1]+nums[2];
}
Arrays.sort(nums);
int dlt = Integer.MAX_VALUE;//记录间隔
int res = Integer.MAX_VALUE;
for(int i=0;i<nums.length-2;i++){
int k = nums.length-1;//指针k
for(int j=i+1;j<nums.length-1&&k>j;){
//指针j
int res_now = nums[i]+nums[j]+nums[k];
int dlt_now = Math.abs(res_now-target);
if(res_now>target){
//如果当前的值大于target,说明了 我们如果想要找到比该值更接近的数只能让k--。在这个过程里面 还需要进行更新操作,即如果当前的间距更加小。则更新记录的值
if(dlt_now<dlt){
res = res_now;
dlt = dlt_now;
}
k--;
}else if(res_now<target){
//如果当前的值小于 target,说明我们需要移动j,在这个过程里面 还需要进行更新操作,即如果当前的间距更加小。则更新记录的值
if(dlt_now<dlt){
res = res_now;
dlt = dlt_now;
}
j++;
}else return res_now; //如果相等则直接返回。相等是最小的间距
}
}
return res;
}
}
复杂度分析:
时间复杂度:O(N2);
空间复杂度:O(log N)。排序需要使用O(logN) 的空间。然而我们修改了输入的数组 nums,在实际情况下不一定允许,因此也可以看成使用了一个额外的数组存储了 nums 的副本并进行排序,此时空间复杂度为 O(N)