【LeetCode】解题16:3Sum Closest

Problem 16: 3Sum Closest [Medium]

Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

Example:

Given array nums = [-1, 2, 1, -4], and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

来源:LeetCode

解题思路

与15题3Sum类似。

  • 使用sort()对数组排序。
  • 遍历数组,并在当前数字nums[i]的后续数字nums[i+1]~nums[n-1]中,使用双指针法寻找与当前数字之和最靠近target的两个数。

减少执行用时的设计:

  • 在N=3时直接返回三数之和。
  • 在遍历以及双指针移动过程中跳过重复的数字。
  • 遍历数组的当前数字nums[i]的三倍与target的差若大于最小差值(即nums[i]*3 - target > min),则之后的循环中必不可能出现更靠近target的结果,可以直接跳出循环。(因为数组已由小到大排序,之后的数字都不小于nums[i],之后的三数之和都不小于nums[i]*3,也就意味着会与target产生更大的差值,因此可以直接舍去接下来的循环过程。)

排序的时间复杂度O(n log n),遍历数组+双指针过程时间复杂度O(n2),总体时间复杂度O(n2)。

要点:排序双指针

Solution (Java)

class Solution {
    public int threeSumClosest(int[] nums, int target) {
        int N = nums.length;
        if(N == 3) return nums[0] + nums[1] + nums[2];
        Arrays.sort(nums);
        int min = Integer.MAX_VALUE;
        int result = 0;
        int last = nums[0];
        int left, right, temp, sum;
        for(int i = 0; i < N-2; i++){
            if(nums[i]*3 - target > min) break;
            if(nums[i] == last && i > 0) continue;
            last = nums[i];
            left = i+1;
            right = N-1;
            while(left < right){
                sum = nums[i] + nums[left] + nums[right];
                if(sum - target == 0){
                    return target;
                }
                else if(sum - target > 0){
                    if(sum - target < min){
                        min = sum - target;
                        result = sum;
                    }
                    temp = nums[right];
                    while(--right > left && nums[right] == temp);
                }
                else{
                    if(target - sum < min){
                        min = target - sum;
                        result = sum;
                    }
                    temp = nums[left];
                    while(++left < right && nums[left] == temp);
                }
            }
        }
        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值