您的位置:首页 > 编程语言 > C语言/C++

leetcode:2sum,2sumSorted,3sum,3sumClosest,4sum,4sumII.[哈希表,双指针]

2017-02-12 16:02 573 查看
2sum:哈希表,再寻求a+b=c过程中可使用哈希表,一次遍历O(n)即可,使用unordered_map<int,int>之find()方法,思路:不存在于表->进哈希表;存在于表,得结果。注意如果不存在,返回[-1,-1],考虑问题要面面俱到。

class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {// O(n),C++ STL hash-->unoredered_map
vector<int> ret(2,-1);
unordered_map<int,int> hash;
for (int i = 0; i < nums.size(); ++i)
{
if(hash.find(target-nums[i])==hash.end())
{
hash[nums[i]]=i;
}else
{
ret[0]=i;
ret[1]=hash[target-nums[i]]
}
}
return ret;

}
};
2sumSorted:已排序好的数组,直接使用双指针i,j前后逼近,时间复杂度O(logn)。
class Solution {// array is alreay sorted,we use double pointers
public:
vector<int> twoSum_sorted(vector<int>& numbers, int target) {
vector<int> ret(2,-1);
int i=0,j=numbers.size()-1;
while(i<j)
{
if(numbers[i]+numbers[j]==target)
{
ret[0]=i+1;
ret[1]=j+1;
return ret;
}else if(numbers[i]+numbers[j]<target)
{
i++;
}else
{
j--;
}
}
return ret;
}
};

3sum:先排序,然后,固定前面的k,后面双指针i,j逼近,注意有重复值时,可跳跃重复值。代码结构中,不能先跳跃重复值,再求和,因为,如果i一直跳跃,可能把j逼的动不了,[0,-2,1,1,3],i跳到1了,j无法跳到1.所以先求和,再跳跃!
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(),nums.end());

for (int k = 0; k <nums.size(); ++k)
{
if(nums[k]>0) break;
if(k>0&&nums[k]==nums[k-1]) continue;

int i=k+1,j=nums.size()-1;
while(i<j)
{
//while(i<j&&nums[i]==nums[i+1]) i++; we can not find this first,beacuse an example [0,-2,1,1,3]
//while(i<j&&nums[j]==nums[j-1]) j--;
if(nums[i]+nums[j]==0-nums[k])
{
res.push_back({(nums[k],nums[i],nums[j])});
while(i<j&&nums[i]==nums[i+1]) i++;
while(i<j&&nums[j]==nums[j-1]) j--;
i++;
j--;
}else if(nums[i]+nums[j]<0-nums[k])
{
j--;
}else
{
i++;
}
}
}
return res;

}
};

3sumClosest:三数之和sum比target小,为了更靠近target,sum就要增大!(无论正负,靠近就是增大或减小),不要想复杂了,跟二分逼近的原理一样的,擅长变通。
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
int mindis=1000000;
int res;
for (int k = 0; k < nums.size(); ++k)
{
if(k>0&&nums[k]==nums[k-1]) continue;

int i=k+1,j=nums.size()-1;
int sum;
while(i<j)// a little translation of question 3sum,be flexible
{ // first i++ then j-- is not right,beacuse it skips many combinations .it doesn't cover all
sum=nums[k]+nums[i]+nums[j];
if(sum==target) return sum;
else if(sum<target)
{
if(target-sum<mindis)
{
mindis=target-sum;
res=sum;
}
i++;
}else
{
if(sum-target<mindis)
{
mindis=sum-target;
res=sum;
}
j--
}

}
}

return res;

}
};

4sum:3sum外面套一层循环即可

class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
set<vector<int>> setvec;
sort(nums.begin(),nums.end());
for (int p = 0; p < nums.size(); ++p)
{
for (int k = p+1; k < nums.size(); ++k)
{
int i=k+1,j=nums.size()-1;
while(i<j)
{
int sum=nums[p]+nums[k]+nums[i]+nums[j];//3sum +for=4sum
if(sum==target)
{
setvec.insert({nums[p],nums[k],nums[i],nums[j]});
while(i<j&&nums[i]==nums[i+1]) i++;
while(i<j&&nums[j]==nums[j-1]) j--;
i++;
j--;
}else if (sum<target) i++;
else j--;
}
}
}

set<vector<int>>::iterator it= setvec.begin();
for(;it!=setvec.end();++it)
{
res.push_back(*it);
}
return res;

}
};

4sumII:unordered_map的迭代器用法,for(auto a:m1) a.first a.second. 能用哈希表的尽量用哈希表

class Solution {
public:
int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
int res=0;
int len=A.size();
unordered_map<int,int>m1,m2;
for (int i = 0; i < len; ++i)
{
for (int j = 0; j < len; ++j)
{
m1[A[i]+B[j]]++;
m2[C[i]+D[j]]++;
}
}
for (auto a:m1)//knowing how to use iterator of unordered_map
{
res+=a.second*m2[0-a.first];
}
return res;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ leetcode 算法