文章目录
leetcode15:15. 三数之和
题目描述
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
Example
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
solution idea
双指针法
三数之和可以解构成在二数之和问题的基础上,将target值变成变化的值。对数组进行遍历,每一个元素的值就是target的取值。
- 为保证不重复,首先对数组进行排序,但不可去重。当target取值相同时,直接跳过即可,这是保证不重复需要注意的其中一点。另一点是在寻找两数之和满足target值时,若遇到相同元素(相同元素一定相邻),可直接跳过。
- 用双指针是相对合适的解法,原因是双指针遍历时,可以结合先剪枝策略,从而降低平均耗时。
- 先剪枝策略:前面的指针所访问的元素大于target时,可提前结束。
class Solution {
public:
/*
** 双指针法
*/
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> results;
int length=nums.size();
if (length<3) return results;
//排序(降序)
sort(nums.begin(),nums.end());
for (vector<int>::iterator it=nums.begin(); it<nums.end()-2; )
{
int tmp=*it;
if (tmp>0) break;
vector<int>::iterator left=it+1;
vector<int>::iterator right=nums.end()-1; //类似于下标索引从0开始,最后一个元素是 *(nums.end()-1)
while(left<right)
{
if(*right<0) break;
if((*left + *right +tmp)>0)
{
int v_temp=*right;
while(left<right && *right==v_temp ) right--;//跳过相等的元素
}
else if((*left + *right +tmp)<0)
{
int v_temp=*left;
while(left<right && *left==v_temp) left++;
}
else
{
vector<int> result={tmp,*left,*right};//保存结果
results.push_back(result);
int v_temp=*right;
while(left<right && *right==v_temp ) right--;//跳过相等的元素
v_temp=*left;
while(left<right && *left==v_temp) left++;
}
}
while(it != nums.end()-2 && *it == tmp) it++;//跳过相等的元素
}
return results;
}
};
Tricks
std::sort
default (1)
template <class RandomAccessIterator>
void sort (RandomAccessIterator first, RandomAccessIterator last);
custom (2)
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
Sorts the elements in the range [first,last) into ascending order.
The elements are compared using operator< for the first version, and comp for the second.
Equivalent elements are not guaranteed to keep their original relative order (see stable_sort).
iterator 迭代器
An iterator is any object that, pointing to some element in a range of elements (such as an array or a container), has the ability to iterate through the elements of that range using a set of operators (with at least the increment (++
) and dereference (*
) operators).
迭代起的运算
迭代器支持的运算
begin 和end 运算符
an iterator pointing to the first/past-the-end element in the sequence
begin和end返回的具体类型由对象是否是常量决定
vector<int> v;
const vector<int> cv;
auto it1=v.begin(); // it1的类型是 vector<int>::iterator
auto it2=cv.begin(); // it2的类型是 vector<int>::const_iterator