每天一道leetcode16-最接近的三數之和

  • 2019 年 10 月 4 日
  • 筆記

以下是昨天的題解

題目

每天一道leetcode16-最接近的三數之和 分類:數組 中文鏈接: https://leetcode-cn.com/problems/3sum-closest/description/ 英文鏈接 https://leetcode.com/problems/3sum-closest/description/

題目詳述

給定一個包括 n 個整數的數組 nums 和 一個目標值 target。找出 nums 中的三個整數,使得它們的和與 target 最接近。返回這三個數的和。假定每組輸入只存在唯一答案。 例如,給定數組 nums = [-1,2,1,-4], 和 target = 1. 與 target 最接近的三個數的和為 2. (-1 + 2 + 1 = 2).

題目詳解

思路

  • 先sort一下array,為啥要sort呢,因為要用到two pointers 來遍歷找兩數之和,只有在從小到大排序之後的結果上,才能根據情況移動left 和right。
  • 首先是如果數組只有3個數字,那麼直接返回這三個數字之和;(最少三個數
  • 當確定好了第一個數字後,就在剩下的array里找兩數之和,在加上第一個數字,用這個tempSum減去target 來得到tempCha;(tempCha就是臨時的一個差值)
  • 比較tempCha與之前保留的cha的值大小,如果比cha小,那麼說明此刻的tempCha就有可能是最小的差,記錄下來這個時候的tempCha和這個時候的可能是最後返回結果的三數之和
  • 利用two pointers 特性, 如果tempSum 比target 小的話,說明我們需要更大的sum,所以要讓left++以便得到更大的sum。 如果tempSum 比target 大的話,我們就需要更小的sum,所以right–。如果相等的話,直接return 就可以了。因為都相等了,那麼差值就等於0,不會有差值再小的了。

代碼

class Solution {      public int threeSumClosest(int[] nums, int target) {          if(nums.length == 3)              return nums[0] + nums[1] + nums[2];          Arrays.sort(nums);          int result = 0;          int cha = Integer.MAX_VALUE;          int tempCha =  0 ;          for(int one=0;one < nums.length-2;one++)          {              int left = one + 1;              int right = nums.length - 1;              while(left < right)              {                  int tempSum = nums[one] + nums[left] + nums[right];                  tempCha = Math.abs(tempSum - target);                  if(tempCha < cha)                  {                      cha = tempCha;                      result = tempSum;                  }                  if(tempSum == target)                  {                      return target;                  }                  if(tempSum < target)                  {                      left++;                  }else{                      right--;                  }                }          }          return result;      }  }  

代碼講解

  • 3-4行 三個數直接返回這三個數之和
  • 9行的意思是固定下來一個數,然後從剩下的數組中進行雙指針操作
  • 11-12行,每次都是從9行固定的數開始,從數組末尾,這兩個端點進行雙指針逼近
  • 15-21行就是如果和tempSum與target的差值tempCha比之前的cha還要小,那麼說明是可能的最小的cha,也就是可能的最接近target的和,把這些中結果保留下來
  • 22-31行就是 利用two pointers 特性, 如果tempSum 比target 小的話,說明我們需要更大的sum,所以要讓left++以便得到更大的sum。 如果tempSum 比target 大的話,我們就需要更小的sum,所以right–。如果相等的話,直接return 就可以了。因為都相等了,那麼差值就等於0,不會有差值再小的了。

經驗教訓

見注釋

class Solution {      public int threeSumClosest(int[] nums, int target) {          if(nums.length == 3)              return nums[0] + nums[1] + nums[2];          Arrays.sort(nums);          int result = 0;          int one = 0;          int tempSum = nums[one] + nums[1] + nums[nums.length-1];          int cha = Integer.MAX_VALUE;          int left = 1;          int right = nums.length - 1;          int tempCha =  0 ;          for(one=0;one < nums.length-2;one++)          {              left = one + 1;              right = nums.length - 1;              while(left < right)              {                  tempSum = nums[one] + nums[left] + nums[right];                  tempCha = Math.abs(tempSum - target);                  if(tempCha <= cha)                  {                      cha = tempCha;                      result = tempSum;//這裡的潛在的最後的正確結果沒注意保存                  }else{                      break;//這裡使用了一個break,我以為tempCha大於cha這一層循環就不用了,但是沒準往中間逼近的時候和還更小了呢,這裡想當然了                  }                  if(tempSum == target)                  {                      return target;                  }                  if(tempSum < target)                  {                      left++;                  }else{                      right--;                  }                }          }          return result;      }  }