3Sum Closest

描述

给定一个n个整数的数组SS中找到三个整数,使得总和最接近给定数量的目标。返回三个整数的和。你可以假设每个输入都只有一个解决方案。

    例如,给定数组S = {-1 2 1 -4},target = 1。

    最接近目标的总和是2.(-1 + 2 + 1 = 2)。

解决方案

和上次做的三个数和为0那个题很像,所以首先要想到的当然就是给这个无序数组排序,这样能降低之后的匹配过程的复杂度。

我又一次本着先做对后看事件复杂度的态度,先按照最传统的方法做出来了,惊喜的是,通过了,虽然时间复杂度还是很高,下面是我写的方法:

public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        int distance = Math.abs(target-(nums[0]+nums[1]+nums[2]));
        int sum = nums[0]+nums[1]+nums[2];
        for(int i=0; i<nums.length-2;i++){
            if(i == 0 || (i > 0 && nums[i] != nums[i-1])){
                for(int j=i+1; j<nums.length-1; j++){
                    if(j == (i+1) || (j > (i+1) && nums[j] != nums[j-1])){
                        for(int n=j+1; n<nums.length; n++){
                            if((n == (j+1) || (n > (j+1) && nums[n] != nums[n-1])) && (distance>Math.abs(target-(nums[i]+nums[j]+nums[n])))){
                                distance = Math.abs(target-(nums[i]+nums[j]+nums[n]));
                                sum = nums[i]+nums[j]+nums[n];
                            }
                        }
                    }
                }
            }
        }
        return sum;
    }

然后看了讨论区中大神们做的,很厉害,其方法还是利用之前那个从两边趋近中间的方法,思想如下:

1、先定义第一个数的位置,然后再以第一个数右边一位的数为最左数,以最后一位数为最右数。

2、把第一个数,最左数和最右数这三个数加和。

3、如果此时三个数的和大于目标数,那么说明最右数过大,那么最右数向左移动一位。重复步骤2。

4、如果三个数和小于目标数,那么说明最左数过小,那么最左数右移动一位。重复步骤2。

5、在进行2/3/4步骤同时,比较最短距离和记录三个数的和,以便最后得到正确结果并返回。

具体代码如下:

public int threeSumClosest1(int[] num, int target) {
        int result = num[0] + num[1] + num[num.length - 1];
        Arrays.sort(num);
        for (int i = 0; i < num.length - 2; i++) {
            int start = i + 1, end = num.length - 1;
            while (start < end) {
                int sum = num[i] + num[start] + num[end];
                //如果此时三个数和大于target,说明最大数过大(即num[end]过大),那么就要减小大数,否则增大小的数(即num[start]过小)
                if (sum > target) {
                    end--;
                } else {
                    start++;
                }
                if (Math.abs(sum - target) < Math.abs(result - target)) {
                    result = sum;
                }
            }
        }
        return result;
    }

  

原文地址:https://www.cnblogs.com/K-artorias/p/7911795.html