LeetCode16-最接近的三数之和 | 算法练习系列

283 阅读2分钟

这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战

前言

今天来一道简单的算法题(虽然LeetCode中说它是中等的题目),最接近的三数之和,这道题题目很简单,但想要做到最优也需要一些思考,还是那句话,最重要的是思路,其它都是扯淡,下面开干

题目描述

给定一个包括n个整数的数组nums和 一个目标值target。找出nums中的三个整数,使得它们的和与target最接近。返回这三个数的和。假定每组输入只存在唯一答案。

示例:

输入:nums = [-1,2,1,-4], target = 1

输出:2

解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

解题思路

  • 本题的题干想当的简单,就单单的一句话,大致意思就是从数组中找出三个数,让他们的和减去输入的target值最小就行了,但注意这里有坑,一定要记得考虑负数的情况,也就是这里应该判断的是这三个数的和减去target的绝对值最小
  • 我看到这道题目的想法就是直接把能组成的所有三个数小组进行对比,这样就得到我想要的结果了,说干就干,直接上代码
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
   var threeSumClosest = function(nums, target) {
            debugger
    let a=0
    let b=1
    let c=2
    let result =0 
    let minValue = 10000000
    while(a<=nums.length-3){
        b=a+1
        while(b<=nums.length-2){
            c=b+1
            while(c<=nums.length-1){
                if(minValue > Math.abs(nums[a]+nums[b]+nums[c]-target) ){
                     minValue =  Math.abs(nums[a]+nums[b]+nums[c]-target)
                     result = nums[a]+nums[b]+nums[c]
                } 
                c++
            }
            b++
        }
        a++
    }
    return result
};

LeetCode运行结果如下

结果.PNG

优化一下

从上面的代码可以看出,直接暴力枚举确实可以解决问题,但时间复杂度是O(N^3),这明显不是最优解

  • 我们可以换一种思路,首先我们把输入的数组进行排序,然后使用一重循环来枚举a,接着用两个指针b和c别指向a+1的位置,nums.length-1的位置,然后比较三者的和于target的关系, 这样就明显减少了我们的比较次数
  • 这是的时间复杂度就来到了O(N^2)
  • 实际上我们还可以进一步优化,那就是当遇到abc相加-target的绝对值是0的时候直接结束判断即可,因为之后已经不可能从在比这个更优的解了

总结

上面提到的暴力枚举和优化中提到的解法其实都能解决问题,但暴力枚举的性能很低,所以最好还是用优化中的思路来写代码,这里只给出了思路,代码大家就自己写吧。gogogo