LeetCode 16. 3Sum Closest
題目要求:給出一個整型數組nums和一個整數target,要求從nums中找出3個整數a,b,c使得它們的和最接近target。
題目給出的框架如下所示:
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
}
};
解題思路
這道題和之前的3Sum極爲相似,原理參考上一篇文章LeetCode 15. 3Sum。
只是條件有所改變從原來的nums[i]+nums[j]+nums[k]與0的比較,變成了nums[i]+nums[j]+nums[k]與target的比較。
但需要注意的是:3Sum的結果可以爲空,本題的結果一定不爲空,因此不能加上循環條件nums[k] < target/3。
具體做法如下:
- 固定一個數k,在它後面找出兩個數i=k+1和j=length-1,i和j不斷向中間移動,使得nums[i]+nums[j]+nums[k]的值儘可能接近target,用minus記錄target與nums[i]+nums[j]+nums[k]的差值,即:minus = target - nums[i] - nums[j] - nums[k];
- 爲了使nums[i]+nums[j]+nums[k]的值儘可能接近target,因此,需要分爲以下3種情況考慮:
若nums[i]+nums[j]+nums[k] == target,則直接返回nums[i]+nums[j]+nums[k];
若nums[i]+nums[j]+nums[k] < target,則爲了使結果靠近target,應當使得i向右移動,nums[i]增大後,三者之和也相應的增大;
若nums[i]+nums[j]+nums[k] > target,則爲了使結果靠近target,應當使得j向左移動,nums[j]減小後,三者之和也相應的減小; - 爲了剔除重複的情況,i和j在移動的時候碰到相同的元素應當繼續向前移動,但是k不能,如果k碰到相同的就移動的話,可能會造成沒有結果的情況,如nums={1,1,1,1}和targt=0。
代碼實現
代碼實現如下:
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int minus = INT_MAX;
for (int k = 0; k < nums.size() - 2; ++k) {
if (k > 0 && nums[k] == nums[k - 1])
continue;
int i = k + 1, j = nums.size() - 1;
while (i < j) {
if (abs(target - nums[i] - nums[j] - nums[k]) < abs(minus)) {
minus = target - nums[i] - nums[j] - nums[k];
}
if (nums[i] + nums[j] + nums[k] == target)
return target;
if (nums[i] + nums[j] + nums[k] < target) {
while (++i < j && nums[i] == nums[i - 1])
; // 跳過重複元素
}
if (nums[i] + nums[j] + nums[k] > target) {
while (i < --j && nums[j] == nums[j + 1])
; // 跳過重複元素
}
}
}
return target - minus;
}
};