15. 三数之和
方法网上有很多,这里主要分析一下用set排重的问题。
先说知识点:
1.set采用等价比较,而不是等值(Effective STL)。就是说不用operator==,只用operator<。
2.set只实现了内置类型的比较函数。
3.当set里面元素相等时,总是返回false。
4.set比较函数的实现方法如下
struct A{
int a;
}
方法一:因为set自动调用less<A>。而less会调用 A的 <。所以可以结构体内定义 <
struct A{
bool operator<(const A& a) const
{
}
}
方法二:不用less,自己定义com
struct cmp
{
bool operator()(const, const){}
}
5.在本题中,set结构为set<vector<int>, cmp>
问题是为什么即使没有cmp,也能实现正确的比较???
原因:
STL实现了vector<int>
的比较函数
template <class T, class Alloc>
bool operator== (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
template <class T, class Alloc>
bool operator< (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
我估摸它的operator< ()是这样子实现的:
struct cmp
{
bool operator()(const vector<int> &a, const vector<int> &b)
{
int nSize = a.size() > b.size()? b.size():a.size();
for (int i = 0; i < nSize; i++)
{
if (!(a[i]<b[i]) && !(a[i]>b[i]))
{
continue;
}
return a[i] < b[i];
}
return a.size() < b.size();
}
};
好了,set<vecotr<int>>
为什么比较正常讲清楚了。下面是代码:
struct cmp
{
bool operator()(const vector<int> &a, const vector<int> &b)
{
int nSize = a.size() > b.size()? b.size():a.size();
for (int i = 0; i < nSize; i++)
{
if (!(a[i]<b[i]) && !(a[i]>b[i]))
{
continue;
}
return a[i] < b[i];
}
return a.size() < b.size();
}
};
vector<vector<int>> threeSum(vector<int>& nums) {
if (nums.size() < 3)
{
return vector<vector<int>>();
}
sort(nums.begin(), nums.end());
set<vector<int>, cmp> clRes;
for (int i = 0; i <= nums.size() - 3; i++)
{
if (nums[i] > 0)
{
break;
}
int nFirstNum = nums[i];
int nTwoSum = 0 - nFirstNum;
int nLeftIdx = i + 1;
int nRightIdx = nums.size() - 1;
while(nLeftIdx < nRightIdx)
{
if (nums[nLeftIdx] + nums[nRightIdx] == nTwoSum)
{
vector<int> clTmpVec({nFirstNum, nums[nLeftIdx], nums[nRightIdx]});
clRes.insert(clTmpVec);
nLeftIdx++;
nRightIdx--;
}
else if (nums[nLeftIdx] + nums[nRightIdx] < nTwoSum)
{
nLeftIdx++;
}
else
{
nRightIdx--;
}
}
}
vector<vector<int>> clVecRes(clRes.begin(), clRes.end());
return clVecRes;
}