LeetCode16.最接近的三數之和
各位朋友們大家好呀,我是你的老朋友冢狐,今天我們來看一道LeetCode上的中等難度的題目——最接近的三數之和問題。希望看完這篇文章後能給各位帶來一些收穫。
題目:
首先我們先來看一下題目的描述:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-J1j4JLzT-1593154112609)(https://raw.githubusercontent.com/iszhonghu/Picture-bed/master/img/20200626110631.png)]
分析
對於這個問題我們先從簡單的場景來分析:
只找一個數
那最簡單的場景無非是找最接近的一數之和,那麼我們只需要維護一個變量:best。best記錄這個目前的最佳值,遇到更合適的就替換這個best直到遍歷完整個數組。
找兩個數的和
再複雜一點就是找最接近的兩個數的和。最簡單的想法就是化簡爲上一種情況,將目標值先減去一個值,然後在去尋找剩下的,但是這樣由於嵌套for循環導致時間複雜度不是很友好,存在優化的空間。
現在問題來了:到底優化的空間在哪裏?如何將這一部分空間節約出來?
上述方法存在的問題就是,當我們第一個已經比目標值小的情況下在去和一個負值相加就更不可能是我們的目標,再往下擴展一步就是,當我們a+b已經小於目標值的情景下,再去找一個比b小的值來和a相加就完全沒有必要了。
- 有序數組加雙指針:
- 那我們先將數組進行排序,然後就得到了一個有序的數組
- 然後left和right兩個指針分別指向第一個和最後一個,將其相加得到sum,然後比較best和sum那個更接近目標值
- 然後判斷sum比目標值大還是小,大的話右指針左移,小的話左指針右移。
找三個數的和
既然有了前兩次的經驗,那我們就轉化爲找兩數之和,即先找一個固定值,然後雙指針。
代碼實現
public int threeSumClosest(int[] nums, int target) {
// 先將數組排序以便和後續雙指針運算
Arrays.sort(nums);
int len = nums.length;
// 賦值默認初始值,
int best = nums[0] + nums[1] + nums[2];
int sum = 0;
// 固定a找b和c
for (int a = 0; a < len; a++) {
// 爲了防止重複查找 b=a+1;
int b = a + 1;
int c = len - 1;
while (b < c) {
sum = nums[a] + nums[b] + nums[c];
if (sum == target) {
return sum;
}
// 判斷是否需要更新最佳值
if (Math.abs(sum - target) < Math.abs(best - target)) {
best = sum;
}
// 判斷雙指針哪一個需要移動
if (sum > target) {
c--;
} else {
b++;
}
}
}
return best;
}
最後
- 如果覺得看完有收穫,希望能給我點個贊,這將會是我更新的最大動力,感謝各位的支持
- 歡迎各位關注我的公衆號【java冢狐】,專注於java和計算機基礎知識,保證讓你看完有所收穫,不信你打我
- 如果看完有不同的意見或者建議,歡迎多多評論一起交流。感謝各位的支持以及厚愛。