LeetCode16、最接近的三数之和

题目描述

在这里插入图片描述

暴力法求解

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)

猜你喜欢

转载自blog.csdn.net/qq_44861675/article/details/108498541
今日推荐