每日一题:最接近的三数之和

83 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情

题目

题目链接

给你一个长度为 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

提示:

  • 3 <= nums.length <= 1000
  • -1000 <= nums[i] <= 1000
  • -104 <= target <= 104

解题

思路:排序+双指针

因为本题是三个数,如果用暴力枚举,时间复杂度就会是O(n^3),我们要降低时间复杂度

  1. 首先对数组进行排序,时间复杂度为O(n log n)
  2. 遍历排序后的数组,将每次遍历出来的值,当作第一个数字i
  3. 第二个数字的确定为 left = i + 1,第三个数字确定为 right = nums.length - 1,就在结尾处。
  4. 每次相加这三个数 num = nums[i] + nums[left] + nums[right],根据他们相加的结果sum,判断sum与目标target的距离,如果更近就更新res
  5. 因为数组有序,所以更新完元素后再比较sumtarget之间的大小关系
    • sum > target 时,则right--
    • sum < target 时,则left++
    • sum == target 时,意味着我们找到了那个元素,返回结果即可
  6. 整个遍历过程,i需要遍历n次,双指针为n次,时间复杂度为O(n^2)O(n^2) + O(n log n) = O(n ^ 2),所以总时间复杂度为 O(n^2)

代码:JAVA

public int threesums(int[] arr,int target) {
    Arrays.sort(arr);
    int res = arr[0] + arr[1] + arr[2];
    for (int i = 0; i < arr.length; i++) {
        int left = i + 1,right = arr.length - 1;
        while (left < right) {
            int sum = arr[i] + arr[left] + arr[right];
            if (Math.abs(target - sum) < Math.abs(target - ans)) {
                ans = sum;
            }
             if (sum > target) {
                right--;
             } else if (sum < target) {
                left++;
             } else {
                return res;
             }

        }
    }
    return res;
}

提交结果:

image.png