3Sum Closest
阿新 • • 發佈:2017-11-28
[] 代碼 中大 態度 時間 大於 又一 得到 target
描述
給定一個n個整數的數組S,在S中找到三個整數,使得總和最接近給定數量的目標。返回三個整數的和。你可以假設每個輸入都只有一個解決方案。
例如,給定數組S = {-1 2 1 -4},target = 1。 最接近目標的總和是2.(-1 + 2 + 1 = 2)。
解決方案
和上次做的三個數和為0那個題很像,所以首先要想到的當然就是給這個無序數組排序,這樣能降低之後的匹配過程的復雜度。
我又一次本著先做對後看事件復雜度的態度,先按照最傳統的方法做出來了,驚喜的是,通過了,雖然時間復雜度還是很高,下面是我寫的方法:
public int threeSumClosest(int[] nums, int target) { Arrays.sort(nums); int distance = Math.abs(target-(nums[0]+nums[1]+nums[2])); int sum = nums[0]+nums[1]+nums[2]; for(int i=0; i<nums.length-2;i++){ if(i == 0 || (i > 0 && nums[i] != nums[i-1])){ for(int j=i+1; j<nums.length-1; j++){ if(j == (i+1) || (j > (i+1) && nums[j] != nums[j-1])){ for(int n=j+1; n<nums.length; n++){ if((n == (j+1) || (n > (j+1) && nums[n] != nums[n-1])) && (distance>Math.abs(target-(nums[i]+nums[j]+nums[n])))){ distance = Math.abs(target-(nums[i]+nums[j]+nums[n])); sum = nums[i]+nums[j]+nums[n]; } } } } } } return sum; }
然後看了討論區中大神們做的,很厲害,其方法還是利用之前那個從兩邊趨近中間的方法,思想如下:
1、先定義第一個數的位置,然後再以第一個數右邊一位的數為最左數,以最後一位數為最右數。
2、把第一個數,最左數和最右數這三個數加和。
3、如果此時三個數的和大於目標數,那麽說明最右數過大,那麽最右數向左移動一位。重復步驟2。
4、如果三個數和小於目標數,那麽說明最左數過小,那麽最左數右移動一位。重復步驟2。
5、在進行2/3/4步驟同時,比較最短距離和記錄三個數的和,以便最後得到正確結果並返回。
具體代碼如下:
public int threeSumClosest1(int[] num, int target) { int result = num[0] + num[1] + num[num.length - 1]; Arrays.sort(num); for (int i = 0; i < num.length - 2; i++) { int start = i + 1, end = num.length - 1; while (start < end) { int sum = num[i] + num[start] + num[end]; //如果此時三個數和大於target,說明最大數過大(即num[end]過大),那麽就要減小大數,否則增大小的數(即num[start]過小) if (sum > target) { end--; } else { start++; } if (Math.abs(sum - target) < Math.abs(result - target)) { result = sum; } } } return result; }
3Sum Closest