240924-16最接近的三数之和

72 阅读1分钟

给你一个长度为 n 的整数数组 nums **和 一个目标值 target。请你从 nums **中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。

假定每组输入只存在恰好一个解。

示例 1:

输入: nums = [-1,2,1,-4], target = 1
输出: 2
解释: 与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

示例 2:

输入: nums = [0,0,0], target = 1
输出: 0

思路

和三数之和一样,只不过条件变成最接近target

public int threeSumClosest(int[] nums, int target) {
        int res = Integer.MAX_VALUE;
        //保证a<b<c只留下abc,去掉bca cab等,同时存在重复元素时候要过滤掉去掉重复元素求解——有序
        //穷举b和c=target-a时候可以用左右双指针向内逼近,时间复杂度为O(N)
        //1.上一道题为了去掉重复元素所以排序 2.为了去掉里面的两层循环使用双指针在有序数组上的求和性质可以优化
        Arrays.sort(nums);
        //有序后就可以for枚举i元素和[i+1,nums.length]内的元素
        for (int i = 0; i < nums.length; i++) {
            int base = target - nums[i];
            int left = i + 1;
            //第一层循环去重
            if (i > 0 && nums[i-1]==nums[i]){
                continue;
            }
            int right = nums.length - 1;
 
             //left和right是两个元素,不能相等
            while (left < right){
                int cur = nums[left] + nums[right] + nums[i];
                res = Math.abs(target - cur) < Math.abs(target - res) ? cur : res;
                //三数和小于target,增加三数和逼近target
                if (cur < target){
                    left++;
                    //跳过相同元素
                    while (left < right && nums[left] == nums[left - 1]) {
                        left++;
                    }
                }else if (cur > target){
                    right--;
                    //跳过相同元素
                    while (left < right && nums[right] == nums[right + 1]) {
                        right--;
                    }
                }else if (cur == target){
                    //剪枝
                    return target;
                }
            }

        }
        return res;
    }
}