(1 / 15 / 16 / 18) NSum問題集合
給定一個整數陣列,返回兩個數的下標位置,他們加起來是一個指定目標值。
你應該認為每個輸入恰有一個解決方案。
例子:
給定num =(2、7、11、15),目標值= 9,
因為num[0]+ num[1]= 2 + 7 = 9,
所以返回[0,1]。
更新(2016/2/13):
返回的格式已經改變了從零開始的索引。請仔細閱讀上述更新描述。
分析:DONE
其實比較簡單的解法是在遍歷陣列時,總是在每個元素後面的所有元素中,即[i+1,n)的範圍內尋找target-nums[i]這個值,如果存在這個值則返回下標i個這個值的下標即可。時間浮渣度為O(n^2),空間複雜度為O(1)。
但是,比較顯然的是可以用雜湊map來加速查詢(因為他是常數時間的查詢),此時可以往前找也可以往後搜尋目的值,方案如下:
一直遍歷陣列
1)在雜湊map中尋找target-nums[i]
2)如果存在則返回這對下標,否則壓入nums[i]到雜湊map中
空間複雜度為O(N),時間浮渣度為O(N),通過所有測試案例耗時16ms
class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { //於2016.6.10徒手重寫 map<int,int> mapping; vector<int> result; for(int i=0;i<nums.size();i++) { if(mapping.find(target-nums[i])!=mapping.end() ) { result.push_back(mapping[target-nums[i]]); result.push_back(i); return result; } mapping[nums[i]]=i; } return result; } };
15. 3Sum
Total Accepted: 102450 Total Submissions: 560117 Difficulty: MediumGiven an array S of n integers, are there elements a, b, c in S such that a + b + c = 0?
Find all unique triplets in the array which gives the sum of zero.
Note:
- Elements in a triplet (a,b,c) must be in non-descending order. (ie, a
- The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)
分析:
暴力破解,時間複雜度是O(n^3),超時
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
if(nums.size()<=2)
return result;
int pos1=0,pos2=0,pos3=0;
for(;pos1<nums.size();pos1++)
{
pos2=pos1+1;
for(;pos2<nums.size();pos2++)
{
pos3=pos2+1;
for(;pos3<nums.size();pos3++)
{
if((nums[pos1]+nums[pos2]+nums[pos3])==0)
{
vector<int> tmpres;
tmpres.push_back(nums[pos1]);
tmpres.push_back(nums[pos2]);
tmpres.push_back(nums[pos3]);
sort(tmpres.begin(),tmpres.end());
result.push_back(tmpres);
}
}
}
}
return result;
}
};
別人的做法:
本體只需要找到三個數相加=0,那麼只需要在遍歷陣列元素時,另外兩個加起來等於負的當前元素即可。
然後利用雙指標查詢這樣的兩個元素。
關鍵詞:先排序,再遍歷,雙指標,防重複操作。
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
int n = num.size();
sort(num.begin(), num.end());//排序
vector<vector<int> > res;
for(int i = 0; i < n-2; i++)
{
if(i > 0 && num[i] == num[i-1])
continue;//重複的元素不用計算
int target = num[i];
twoSum(num, i+1, -target, res);//從當前元素後面開始找相加為目標值(當前元素的負值)的兩個數字
}
return res;
}
void twoSum(vector<int> &sortedNum, int start, int target, vector<vector<int> >&res)
{
int head = start, tail = sortedNum.size() - 1;
while(head < tail)
{
int tmp = sortedNum[head] + sortedNum[tail];
if(tmp < target)
head++;
else if(tmp > target)
tail--;
else//相等,獲取結果
{
res.push_back(vector<int>{sortedNum[start-1], sortedNum[head], sortedNum[tail]});
//為了防止出現重複結果,跳過相等的情況
int k = head+1;
while(k < tail && sortedNum[k] == sortedNum[head])
k++;
head = k;
k = tail-1;
while(k > head && sortedNum[k] == sortedNum[tail])
k--;
tail = k;
}
}
}
};
16. 3Sum Closest
My Submissions Total Accepted: 76863 Total Submissions: 263989 Difficulty: MediumGiven an array S of n integers, find three integers in S such 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).
分析:
a+b+c儘可能接近target,那麼如前面一題所示,當遍歷到元素a時,
我們在其後尋找b和c之和接近target-a的兩個數即可。而儘可能接近的標準就是兩者之差儘可能小。
基於上面一題的提示,這個題就簡單很多了,如程式碼所示:
class Solution {
public:
int threeSumClosest(vector<int>& num, int target) {
int n = num.size();
sort(num.begin(), num.end());//排序
int result=0, min_gap=INT_MAX;
for(int i = 0; i < n-2; i++)
{
if(i > 0 && num[i] == num[i-1])
continue;//重複的元素不用計算
int tmptarget =target - num[i];
if(twoSum(num, i+1, tmptarget, result,min_gap)) //從當前元素後面開始找相加接近目標值的兩個數字之和
break;
}
return result;
}
bool twoSum(vector<int> &sortedNum, int start, int tmptarget, int &result,int &min_gap)
{
int head = start, tail = sortedNum.size() - 1;
while(head < tail)
{
int tmp = sortedNum[head] + sortedNum[tail]; //tmp要儘可能接近tmptarget,甚至相等
if(tmp < tmptarget)
{
if(min_gap > abs(tmptarget-tmp))
{
min_gap=abs(tmptarget-tmp);
result=sortedNum[start-1]+ sortedNum[head]+ sortedNum[tail];
}
head++;
}
else if(tmp > tmptarget)
{
if(min_gap > abs(tmptarget-tmp))
{
min_gap=abs(tmptarget-tmp);
result=sortedNum[start-1]+ sortedNum[head]+ sortedNum[tail];
}
tail--;
}
else//相等,相差距離絕對最短,直接獲取結果退出即可。
{
result=sortedNum[start-1]+ sortedNum[head]+ sortedNum[tail];
return true;
}
}
return false;
}
};
18. 4Sum
Total Accepted: 71829 Total Submissions: 301721 Difficulty: MediumGiven an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
- Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
- The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0. A solution set is: (-1, 0, 0, 1) (-2, -1, 1, 2) (-2, 0, 0, 2)
分析:
與前面的題類似,不在累述!
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& num, int target) {
int n = num.size();
if(n < 4)
return result;
sort(num.begin(), num.end());//排序
for(int i = 0; i < n-3; i++)
{
for(int j=i+1;j<n-2;j++)
{
int tmptarget =target - num[i]-num[j];
twoSum(i,num, j+1, tmptarget);//從當前元素後面開始找相加接近目標值的兩個數字之和
while(j < n-2&&num[j+1]==num[j])//防重複答案
j++;
}
while(i < n-3 && num[i+1]==num[i])//防重複答案
i++;
}
return result;
}
void twoSum(int i,vector<int> &sortedNum, int start, int target)
{
int head = start, tail = sortedNum.size() - 1;
while(head < tail)
{
int tmp = sortedNum[head] + sortedNum[tail];
if(tmp < target)
head++;
else if(tmp > target)
tail--;
else//相等,獲取結果
{
result.push_back(vector<int>{sortedNum[i],sortedNum[start-1], sortedNum[head], sortedNum[tail]});
//為了防止出現重複結果,跳過相等的情況
int k = head+1;
while(k < tail && sortedNum[k] == sortedNum[head])
k++;
head = k;
k = tail-1;
while(k > head && sortedNum[k] == sortedNum[tail])
k--;
tail = k;
}
}
}
private:
vector<vector<int>> result;
};
注:本博文為EbowTang原創,後續可能繼續更新本文。如果轉載,請務必複製本條資訊!
原文地址:http://blog.csdn.net/ebowtang/article/details/50320391
原作者部落格:http://blog.csdn.net/ebowtang
本部落格LeetCode題解索引:http://blog.csdn.net/ebowtang/article/details/50668895