查詢陣列中和為某給定值的三元組
阿新 • • 發佈:2019-02-08
問題描述
給定一個數組arr,以及一個數字target。求陣列中和為target的三個數。要求給出所有解。陣列中的每個數在每組解中只能出現一次。
解法
方法一:如果用暴力方法,時間複雜度是o(n3)
方法二:利用C++11中的unordered_multimap,本題複雜度可降至O(n2)
#include<iostream>
#include<vector>
#include<unordered_map>
#include <set>
#include <algorithm>
using namespace std ;
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num, int sum) {
unordered_multimap<int, int> hashmap;
vector<vector<int> > result;
for(int i=num.size()-1; i>=0; i--)
{
hashmap.insert( {num.at(i), num.size()-i-1 } );
}
/*
for(auto iter1=hashmap.begin(); iter1!=hashmap.end(); iter1++)
{
cout<<(*iter1).first<<" ";
cout<<(*iter1).second<<endl;
}
cout<<endl;
*/
for(auto iter1=hashmap.begin(); iter1!=hashmap.end(); iter1++)
{
int target = sum -(*iter1).first;
auto iter = iter1;
iter++;
if (iter == hashmap.end() )
continue;
for(auto iter2=iter; iter2!=hashmap.end(); iter2++)
{
auto iterres = hashmap.equal_range( target - (*iter2).first );
if (iterres.first == iterres.second)//下界pair和上界pair相等,沒找到
{
continue;
}
for(auto get=iterres.first; get!=iterres.second; get++)
{
//get遍歷所有pair(一對mapiterator),(*get)取出一個pair,(*get).second表示第二個map變數
//if (get == hashmap.end() || (*iter1).second >= (*iter2).second || (*iter2).second >= (*get).second )
if (get == hashmap.end() || (*iter1).second == (*iter2).second || (*iter2).second == (*get).second || (*iter1).second == (*get).second ) //後面三個都不能遺漏!
{
continue;
}
int res = (*get).first;
int arr[] = { (*iter2).first, (*iter1).first, res};
sort(arr, arr+3);
vector<int> trip(arr, arr+3);
result.push_back(trip);
}
}
}
set< vector<int> > tmpres;
for(int i=0; i<result.size(); i++)
{
tmpres.insert( result.at(i) );
}
result.clear();
for(auto iter=tmpres.begin(); iter!=tmpres.end(); iter++)
{
result.push_back( *iter );
}
return result;
}
};
int main()
{
Solution sol;
//int arr[] = {-1, 0, 1, 2, -1, -4};
int arr[] = {7,5,-8,-6,-13,7,10,1,1,-4,-14,0,-1,-10,1,-13,-4,6,-11,8,-6,0,0,-5,0,11,-9,8,2,-6,4,-14,6,4,-5,0,-12,12,-13,5,-6,10,-10,0,7,-2,-5,-12,12,-9,12,-9,6,-11,1,14,8,-1,7,-13,8,-11,-11,0,0,-1,-15,3,-11,9,-7,-10,4,-2,5,-4,12,7,-8,9,14,-11,7,5,-15,-15,-4,0,0,-11,3,-15,-15,7,0,0,13,-7,-12,9,9,-3,14,-1,2,5,2,-9,-3,1,7,-12,-3,-1,1,-2,0,12,5,7,8,-7,7,8,7,-15};
vector<int> num(arr, arr+200);
vector<vector<int> > res = sol.threeSum(num, 10);
for(int i=0; i<res.size(); i++)
{
for(int j=0; j<res.at(i).size(); j++)
{
cout<<res.at(i).at(j)<<" ";
}
cout<<endl;
}
return 0;
}
以上解法(稍加修改),提交給leetcode(第15題)後仍然報錯(Time Limit Exceeded)。難道有更低複雜度的解法嗎?
希望有高手能指點一二。
方法三:先排序,然後二分查詢,複雜度可降至O(nlogn)
vector<vector<int> > threeSum(vector<int> &num)
{
vector<vector<int> > res;
if(num.empty())
return res;
sort(num.begin(), num.end()); //nlogn
for(int i=0; i+2<num.size(); i++) //n
{
if(i>0 && num[i] == num[i-1])
continue;
int left(i+1), right(num.size()-1);
while(left < right)//logn
{
if(left>i+1 && num[left] == num[left-1])
{
left++;
continue;
}
if(right < num.size()-1 && num[right] == num[right+1])
{
right--;
continue;
}
int sum = num[i] + num[left] + num[right];
if(sum < 0) left++;
else if(sum > 0) right--;
else
{
res.push_back( vector<int> {num[i], num[left], num[right]} );
right--;
left++;
}
}
}
return res;
}
同理,如果需要查詢陣列中和為某給定值的四元組,用法三解決,時間複雜度為