题目描述(中等难度)

16. 3Sum Closest - 图1

上一道题很类似,只不过这个是给一个目标值,找三个数,使得他们的和最接近目标值。

解法一 暴力解法

遍历所有的情况,然后求出三个数的和,和目标值进行比较,选取差值最小的即可。本以为时间复杂度太大了,神奇的是,竟然 AC 了。

  1. public int threeSumClosest(int[] nums, int target) {
  2. int sub = Integer.MAX_VALUE; //保存和 target 的差值
  3. int sum = 0; //保存当前最接近 target 的三个数的和
  4. for (int i = 0; i < nums.length; i++) {
  5. for (int j = i + 1; j < nums.length; j++)
  6. for (int k = j + 1; k < nums.length; k++) {
  7. if (Math.abs((nums[i] + nums[j] + nums[k] - target)) < sub) {
  8. sum = nums[i] + nums[j] + nums[k];
  9. sub = Math.abs(sum - target);
  10. }
  11. }
  12. }
  13. return sum;
  14. }

时间复杂度:O(n³),三层循环。

空间复杂度:O(1),常数个。

解法二

受到上一题的启发,没有看的,推荐大家可以看一下。我们完全可以先将数组排序,然后先固定一个数字,然后利用头尾两个指针进行遍历,降低一个 O(n)的时间复杂度。

如果 sum 大于 target 就减小右指针,反之,就增加左指针。

  1. public int threeSumClosest(int[] nums, int target) {
  2. Arrays.sort(nums);
  3. int sub=Integer.MAX_VALUE;
  4. int sum=0;
  5. for(int i=0;i<nums.length;i++){
  6. int lo=i+1,hi=nums.length-1;
  7. while(lo<hi){
  8. if(Math.abs((nums[lo]+nums[hi]+nums[i]-target))<sub){
  9. sum=nums[lo]+nums[hi]+nums[i];
  10. sub=Math.abs(sum-target);
  11. }
  12. if(nums[lo]+nums[hi]+nums[i]>target){
  13. hi--;
  14. }else{
  15. lo++;
  16. }
  17. }
  18. }
  19. return sum;
  20. }

时间复杂度:如果是快速排序的

16. 3Sum Closest - 图2

再加上 O(n²),所以就是 O(n²)。

空间复杂度:O(1)。

和上一道题非常非常的相似了,先对数组排序,然后利用两头的指针,可以说是十分的优雅了。

windliang wechat

添加好友一起进步~

如果觉得有帮助的话,可以点击 这里 给一个 star 哦 ^^

如果想系统的学习数据结构和算法,强烈推荐一个我之前学过的课程,可以点击 这里 查看详情