描述:给定一个无序数组,判断能否在数组中找到两个数使得和为给定值,返回所有这样的元组。
输入:Array={-1,0,1,2,-1,4},sum=1。
输出:(0,1),(--1,2)。
思路一:暴力法,做两次循环,依次查找符合条件的二元组。时间复杂度为平方级,空间复杂度为1。
#include<vector>
class Solution{
public:
vector<vector<int> > twosum(int A[],int n,int sum)
{
vector<vector<int> > res;
for(int i=0;i<n-1;i++)
{
for(int j=i+1;j<n;j++)
{
if(A[i]+A[j]==sum)
{
res.push_back({A[i],A[j]});
}
}
}
return res;
}
};
思路二:由于无须返回索引,只返回元素数值,则可先进行排序工作,再利用左右夹逼寻找符合条件的二元组。时间复杂度与排序一致为对数等级,空间复杂度为1。
#include<vector>
#include<algorithm>
class Solution{
public:
vector<vector<int> > twosum(int A[],int n,int sum)
{
vector<vector<int> > res;
if(n<2) return res;
sort(A,A+n);
int i=0;
int j=n-1;
while(i<j)
{
if(A[i]+A[j]<sum)
{
i++;
}
else if(A[i]+A[j]>sum)
{
j--;
}
else
{
vector<int> tmp;
tmp.push_back(A[i]);
tmp.push_back(A[j]);
res.push_back(tmp);
}
}
return res;
}
};
扩展:若是要寻找符合和为定值的三元组该如何设计?
思路一:暴力法,时间复杂度为立方级,代码省略。
思路二:先排序,然后做左右夹逼,注意跳过重复的数字,时间复杂度为平方级,空间复杂度为1。
#include<vector>
class Solution{
public:
vector<vector<int> > threeSum(int A[],int n,int sum)
{
vector<vector<int> > res;
if(n<3) return res;
sort(A,A+n);
for(int i=0;i<n-2;i++)
{
int j=i+1;
if(i>0&&A[i]==A[i-1]) continue;//跳过重复情况
int k=n-1;
while(j<k)
{
if(A[j]+A[k]<sum-A[i])
{
j++;
}
else if(A[j]+A[k]>sum-A[i])
{
k--;
}
else
{
vector<int> tmp;
tmp.push_back(A[i]);
tmp.push_back(A[j]);
tmp.push_back(A[k]);
res.push_back(tmp);
j++;
k--;
while(A[j]==A[j-1]&&A[k]==A[k+1]&&j<k)j++;
}
}
}
return res;
}
};
由此可见,若需寻找K个数为定值和,则需要进行K-2次循环,并在循环体内做左右夹逼,注意夹逼时的边界,若有重复数值则跳过。