链接:
18. 四数之和
题意:
一个数组n,一个目标值t,在数组内找四个数字和等于t,求能有多少种组合
解:
0716:一看怎么昨天卡没打,原来昨天做的第一题不是每日一题,麻了
n很小,200,那么先排序,然后弄一个双指针开双循环l,r
,确定每个组合的最大数字-数字4和最小数字-数字1,然后计算t-num1-num4
,就可以得到该组合对应的num2+num3 我们设为tL
,然后再弄一个双指针ll,rr
在l,r
内找,这时,由于数组已经排序了,所以如果nums[ll]+nums[rr]<tL
就右移LL,如果nums[ll]+nums[rr]>tL
就左移RR
当nums[ll]+nums[rr]==tL
时,我们只需要将其和记录结果的容器里最后一个比较是否相同就可以达到去重的效果(我直接用了暴力比较QWQ)
去重:
1、由于已经排序,所以当新的L和上一个L相同时,跳过。相同数字第一个遇到的一定提供最大的范围(即最小的L),比如 3,3,0,0,0,0…,取第一个3作为L,num2-4还可以选择第二个3,和后面的所有数字;选取第二个3做为L,num2-4只能选择后面的数字,所以选取第二个3做为L所推导的结果包含在取第一个3作为L的结果
2、现在已经确定了该组合的第一个数字num1=nums[L]
,这边要开第二重循环去选取第四个数字num4=nums[R]
,同样,当新的R跟上一个R相同时,跳过,原因同 1
3、确定了num1和num4
,再找num2和num3
就很简单了,上面也提过了,不用双循环,顶多遍历一遍 l,r
4、由于num1逐渐增大且不重复,在同一个num1下num4逐渐减小且不重复,所以答案容器里末尾要么是不同的num1开头,要么是相同的num1开头不同的num4结尾,要么是相同的num1num4,前面两种情况和现在明显不相同,在第三种情况下,由于LL和RR
的起始值固定,且移动方向固定(向数组中间),且数组有序,所以如果不和容器末尾相同,则在容器中一定不存在与之相同的答案
5、由此可知,容器中答案排序是:num1从小到大,num1相同时num4从大到小,num1和num4均相同时num2num3从两边到中间
实际代码:文章来源:https://www.toymoban.com/news/detail-566853.html
#include<bits/stdc++.h>
using namespace std;
bool comp(const vector<int>& A,const vector<int>& B)
{
for(int i=0;i<4;i++)
{
if(A[i]!=B[i])return true;
}
return false;
}
vector<vector<int>> fourSum(vector<int>& nums, int target)
{
sort(nums.begin(),nums.end());//先排序
//for(auto i:nums) cout<<i<<" ";
//cout<<endl;
vector<vector<int>>ans;int lg=nums.size();
for(int l=0,r=lg-1;l<r;l++)
{
if(l && nums[l-1]==nums[l] )continue;//确定数字1 不重复
for(;l<r;r--)
{
if(r<lg-1 && nums[r+1]==nums[r]) continue;//确定数字4 在当前数字1不重复
//cout<<l<<"-N1-"<<r<<endl;
long long targetL=(long long)target-nums[l]-nums[r];//新的目标
for(int ll=l+1,rr=r-1;ll<rr;)
{
//cout<<ll<<"-N2-"<<rr<<endl;
long long now=(long long)nums[ll]+nums[rr];//当前值
if(now==targetL)
{
vector<int>temp{nums[l],nums[ll],nums[rr],nums[r]};
//去重
if(!ans.empty() && comp( temp,*(ans.rbegin()) )) ans.push_back(temp);
if(ans.empty()) ans.push_back(temp);
ll++;rr--;
}
else if(now<targetL) ll++;
else rr--;
}
}
r=lg-1;//重置右指针
}
return ans;
}
int main()
{
vector<int> nums;int target;
cin>>target;int temp;
while(cin>>temp)
{
nums.push_back(temp);
}
vector<vector<int>>ans=fourSum(nums,target);
for(auto &i:ans)
{
for(auto j:i)
{
cout<<j<<" ";
}
cout<<endl;
}
return 0;
}
限制:文章来源地址https://www.toymoban.com/news/detail-566853.html
1 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109
到了这里,关于2023-07-15力扣每日一题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!