算法小知识-----04.28-----最接近的三数之和

200 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第26天,点击查看活动详情

今天周四,快乐的是快要放假了,死亡的是今晚要上线我的功能

最接近的三数之和

该题出自力扣的16题 - 最接近的三数之和【中等题】

审题

给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。

  • 题意很简单,就是给出一个数组,找出数组中存在的三个数,相加总和最接近目标target的总和
  • 对数组进行排序后,可以更直观地了解到接近的数
  • 解法: 排序 + 双指针
    • 对数组进行排序,排序是为了更为直观地找到接近的数,不需要全局搜索
    • 双指针,其实也可以使用三指针,直接指向目标数
      • 初始总和等于 最小的三个数,也就是索引下标的0、1、2
      • 遍历整个数组,在内部进行while循环获取最小值,并且每次循环继续
      • 每一次枚举的过程中,尝试从边界的left元素和right元素,根据与目标值的关系,选择左元素右移还是右元素左移。
  • 本来如果使用暴力循环的话,就是三重for循环,那就是时间复杂度为O(n^3),但是如果使用排序后的双指针方法,时间复杂度为O(n^2)
  • 其中的一些小巧妙,就是如果 最小值等于目标值的时候,则可以剪枝,直接返回即可
  • 空间复杂度为O(lgn),因为排序的内部使用了副本存储

编码

class Solution {
    public int threeSumClosest(int[] nums, int target) {
        //排序 + 双指针
        Arrays.sort(nums);
        int min = nums[0] + nums[1] + nums[2];
        for (int i = 0;i<nums.length -2;i++){
            int l = i +1,r = nums.length -1;
            while (l<r){
                int threeSum = nums[i] + nums[l] + nums[r];
                if (Math.abs(threeSum - target) < Math.abs(min - target)){
                    min = threeSum;
                }
                if (threeSum > target){
                    r--;
                }else if (threeSum<target){
                    l ++;
                }else {
                    return target;
                }
            }
        }
        return min;
    }
}

image.png