LeetCode-16.最接近的三数之和 双指针法

这里是题目描述:LeetCode-16.最接近的三数之和

本题的直观做法是:列举出所给的数组nums中所有的的三数组合,寻找出所有三数之和中与target最接近的。这种方法需要对数组nums进行三层遍历,时间复杂度 O(n3) 。接下来我们使用一种基于双指针的解法,时间复杂度被简化为 O(n2)

双指针解法

第一步,对数组nums进行升序排序。这里我们要引入一个经验之谈:对于许多题干中给出一个数组的问题,如果没有要求不能破坏原数组的顺序结构,那么我们可以尝试对数组进行排序,也许可以基于排序后的数组得到时间或空间效率更优的解法

对于数组中的任意三个数字,一定有左边的数字,中间的数字和右边的数字,依次尝试将中间的数字固定为nums[1]、nums[2]、...nums[n-2],每次将左右两边的数字初始化为中间数字左边第一个数字和右边第一个数字,如图:
在这里插入图片描述
当此时的三数之和sum大于target时,我们希望减小sum以达到更接近target的目的,于是我们将指向左边数字的指针left左移一位;如果sum小于target时,我们希望增大sum以达到更接近target的目的,于是我们将指向右边数字的指针right右移一位;在此过程中记录并更新最接近targetsum,直到left无法再左移或right无法再右移;便尝试下一个中间数字。特别地,如果有遇到sum==target,便可直接将sum返回为结果

题解代码:

class Solution {
   public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        int nearest=nums[0]+nums[1]+nums[2];
        for(int i=1;i<nums.length-1;i++)
        {
            int p1=i-1,p2=i+1;
            while(p1>=0 && p2<nums.length)
            {
                int sum=nums[i]+nums[p1]+nums[p2];
                if(sum==target)
                {
                    return target;
                }
                if(Math.abs(target-sum)<Math.abs(target-nearest))
                {
                    nearest=sum;
                }
                if(sum>target)
                {
                    p1-=1;
                }
                else
                {
                    p2+=1;
                }
            }
        }
        return nearest;
    }
}

时间复杂度:排序需要O(nlogn),双指针寻找最接近的三数和需要尝试O(n)的中间数,每个中间数需要尝试O(n)的左右数字,因此总时间复杂度为O(n2)

空间复杂度:O(1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值