两数,三数,四数之和问题剖析
博主有话要吐槽
话不多说,开始剖析问题
你一定遇到以下问题,对其头脑发热:
题目的目的: 给定一个序列(未排序),多数相加等于特定值,找出其所有符合条件的所有 多数 序列。
讲论解法
1. 我们讲解以下 双数 的解法: 左右指针法(双指针)
2. 左指针 L + 右指针 R 索引的序列元素值等于给定值,则记录其序列,并++L, – R 操作,缩短区间准备下一次查找 相加的值等于 目标值的 L,R 指向元素
3. 左指针 L + 右指针 R 索引的序列元素值小于给定值,说明当前 L 索引到的值小了,需要向右继续移动,指向次大的值,继续判定
4. 左指针 L + 右指针 R 索引的序列元素值大于给定值,说明当前 R 索引到的值大了,需要向左继续移动,指向次小的值,继续判定
5. 其可查询条件为 L < R
注意: 由于是查找不重复的二数之和,因此当我们遇到已经使用过的左右值(该值符不符合都无所谓),都要在进行移动时对其进行判重,重复的话过滤掉。
这里有些爱问题的的小朋友就想问了,万一 重复的元素相加就是等于给定值呢,我们过滤掉不就失去了其结果了吗,事实上我们是在使用过该重复元素的一个元素已经判定其不合格了,假若它们真的相加等于给定值,那 L + R 一定会指向到这两个元素的。
我们用简单的例子分析一下我们的思路处理上述的情况:
2. 我们讲解 三数之和 的解法: 占位左右指针法(双指针)
这个解法的思路是这样的:
将三个数的一个数固定,利用双指针在剩余区间内的元素中去找符合条件的剩余两个数。
- 当first_num 固定在第一位时且符合条件的 L-R 区间内的剩余两数找全后,移动 first_num 固定在下一个位置上,这样就能完成所有符合的查找。
注意: 且 first_num 移动时,注意判重操作,避免重复三数项。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
if(nums.size()<=2)
return {};
sort(nums.begin(),nums.end());
for(decltype(nums.size()) i=0;i!=nums.size()-2;++i){
int l=i+1,r=nums.size()-1;
while(l<r){
if(nums.at(i)+nums.at(l)+nums.at(r) == 0) {
ivecSet.push_back({nums.at(i),nums.at(l),nums.at(r)});
int v1=nums.at(l),v2=nums.at(r);
while(nums.at(++l)==v1 && l<r);
while(nums.at(--r)==v2 && r>l);
}
else if(nums.at(i)+nums.at(l)+nums.at(r) > 0) --r;
else if(nums.at(i)+nums.at(l)+nums.at(r) < 0) ++l;
}
while(i+1 !=nums.size()-2 && nums.at(i) == nums.at(i+1))
++i;
}
return ivecSet;
}
private:
vector<vector<int>> ivecSet;
};
3. 我们讲解 四数之和 的解法: 占两位左右指针法(双指针)
哈哈,占两个位置,利用双指针对剩余 区间进行查找即可