LeetCode之16----3Sums Closest
題目:
Given an arraySofnintegers, find three integers inSsuch that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have
exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
題目大意:
給定一個數(shù)組S和一個目標值target,在S中尋找三個數(shù),使它們的和最接近target。返回三個數(shù)的和。
思路:
一、暴力求解法:
大體思路是用一個變量記錄最小差值和要返回的值,然后枚舉出全部可能的組合,推斷最小差值是不是小于記錄值。假設(shè)小于最小值則更新記錄的最小值和終于結(jié)果。暴力求解法的時間復(fù)雜度是O(n^3)。可是能夠通過一定的推斷使得程序的循環(huán)次數(shù)減少,從而通過測試。推斷例如以下:
(1)、假設(shè)剛好獲得了target。則直接返回。
(2)、三重循環(huán)中假設(shè)碰到與上一次推斷的數(shù)字同樣則直接跳過(由于已經(jīng)在上一次推斷過)
二、3Sums解法的改進版:
大體思路是先排序,用一個變量dis保存距離,用tmp保存候選數(shù)。然后每次選擇一個數(shù)字,先讓這個數(shù)字和最大的兩個數(shù)字相加,假設(shè)小于目標值說明和目標值相等的概率為零(即:差值為0的概率為0)。所以保存三個數(shù)字的和進tmp,保存差值進dis;假設(shè)大于目標值,說明還有可能使得結(jié)果和目標值相等(即:差值為0的概率不為0),所以問題就變成了3Sums中固定一個值然后求另外兩個值的問題了(也看一看作是2Sums問題)僅僅只是在尋找是否能和目標值相等的路上保存下來不相等時的最小差值進dis。在這個撒u你法中也有一些邊界調(diào)節(jié)能夠直接得到答案:
(1)、等于target,直接返回target
(2)、假設(shè)最大的三個數(shù)加起來還小于目標值,則最接近的就是這三個數(shù)相加
(3)、假設(shè)最小的三個數(shù)加起來還大于目標值,則最接近的就是這三個數(shù)相加
(4)、假設(shè)當前處理過的數(shù)字上一次處理的數(shù)字同樣,則不再處理
代碼:
暴力法:
class Solution {
public:
int threeSumClosest(std::vector<int>& nums, int target) {
int result = target, dis = INT_MAX, dis_tmp, tmp;
if (nums.size() == 0) {
result = 0;
}
for (int i = 0; i < nums.size(); ++i) {
if (i != 0 && nums[i] == nums[i - 1]) {
continue;
}
for (int j = i + 1; j < nums.size(); ++j) {
if (j != i + 1 && nums[j] == nums[j - 1]) {
continue;
}
for (int k = j + 1; k < nums.size(); ++k) {
if (k != j + 1 && nums[k] == nums[k - 1]) {
continue;
}
tmp = nums[i] + nums[j] + nums[k];
dis_tmp = abs(tmp - target);
if (dis_tmp < dis) {
dis = dis_tmp;
result = tmp;
if (result == target) {
return target;
}
}
}
}
}
return result;
}
};
3Sums改進法:
class Solution {
public:
int threeSumClosest(std::vector<int>& nums, int target) {
const int n = nums.size();
sort(nums.begin(),nums.end());
//假設(shè)最大的三個數(shù)加起來還小于目標值,則最接近的就是這三個數(shù)相加
if(nums[n-1] + nums[n-2] + nums[n-3] <= target) {
return nums[n-1] + nums[n-2] + nums[n-3];
}
//假設(shè)最小的三個數(shù)加起來還大于目標值,則最接近的就是這三個數(shù)相加
if(nums[0] + nums[1] + nums[2] >= target) {
return nums[0] + nums[1] + nums[2];
}
int tmp; //候選數(shù)
int dis = INT_MAX; //距離
//由于要選擇三個數(shù),所以i < n - 2
for (int i = 0; i < n-2; i++) {
//假設(shè)當前處理過的數(shù)字上一次處理過,則不再處理
if (i != 0 && nums[i] == nums[i-1]) {
continue;
}
//假設(shè)當前掃描的值加上最大的三個數(shù)字之后假設(shè)還小于目標值
//說明和目標值相等的概率為零(即:差值為0的概率為0)
if (nums[i] + nums[n-1] + nums[n-2] <= target) {
tmp = nums[i] + nums[n-1] + nums[n-2];
if (tmp == target) {
return target;
}
dis = tmp - target; //差值最小等于候選值減去目標值
continue;
}
//假設(shè)和最大的三個數(shù)字相加之后大于目標值,說明還有希望找到差值為0的值
//接下來就是求2Sums問題了(不同的一點是加了一個差值最小的推斷)
int target2 = target - nums[i];
int j = i + 1;
int k = n - 1;
while (j < k) {
const int sum2 = nums[j] + nums[k];
if (abs(sum2 - target2) < abs(dis)){
dis = sum2 - target2;
}
if(sum2 > target2) {
k--;
}
else if(sum2 < target2) {
j++;
}
else {
return target;
}
while (nums[j] == nums[j-1]) {
j++;
}
while(nums[k] == nums[k+1]) {
k--;
}
}
}
return target + dis;
}
};
總結(jié)
以上是生活随笔為你收集整理的LeetCode之16----3Sums Closest的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: R语言函数总结(转)
- 下一篇: nodejs插件化框架——minimaj