一个例子:
根据这个问题很容易想到用一个四重循环来写,通过暴力求解得方法,代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAX_N = 50;
int main()
{
int n,m,k[MAX_N];
bool f = false;//判断是否能找到和为m得四个数字
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%d",k[i]);
}
for(int a=0;a<n;a++)
{
for(int b=0;b<n;b++)
{
for(int c=0;c<n;c++)
{
for(int d=0;d<n;d++)
{
if(k[a]+k[b]+k[c]+k[d] == m)
{
f = true;
}
}
}
}
}
if(f)
puts("yes");
else
puts("no");
return 0;
}
/*
n=3
m=9
k={1,3,5}
no
*/
更快的方法:二分查找
我们发现用四重循环的时间复杂度为O(n4),我们利用二分查找来代替最里面那一层的循环,在用二分查找之前需要我们排序,而排序的时间复杂度为O(nlogn),二分查找的时间复杂度为O(logn),代替最里层的循环后,总时间复杂度为O(n3logn),所以时间复杂度为O(n^3logn)。
- 代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAX_N = 50;
int n,m,k[MAX_N];
bool Binary_Search(int x)
{
int l=0,r=n;//这里要求r必须等于n,也就是说要多出一个无用的数组位,因为当x=k[n-1]时,l最终会等于n-1,如果r=n-1则会提前退出循环
while(r-l >= 1)
{
int i = (r+l)/2;
if(k[i] == x) return true;
else if(k[i] < x) l = i+1;
else r = i;
}
return false;
}
int main()
{
bool f = false;//判断是否能找到和为m得四个数字
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%d",&k[i]);
}
sort(k,k+n);//将数组排序
for(int a=0;a<n;a++)
{
for(int b=0;b<n;b++)
{
for(int c=0;c<n;c++)
{
if(Binary_Search(m-k[a]-k[b]-k[c]))
f = true;
}
}
}
if(f)
puts("yes");
else
puts("no");
return 0;
}
/*
n=3
m=9
k={1,3,5}
no
*/
再优化:
- 再使用了二分查找之后时间复杂度为O(n^3logn),可以利用二分查找进一步的优化,我们可以将四重循环的内两层循环换成二分查找,这时候的式子为k[c]+k[d] = m-k[a]-k[b],我们需要一个数组来保存k[c]+k[d]的所有情况。
- 这时候的时间复杂度:
- 1.排序时间复杂度:O(n^2logn)
- 2.循环加二分查找复杂度:O(n^2logn)
- 到这里我们可以发现,再去一层循环已经没有意义了,因为此时的数组排序时间复杂度为O(n^3logn).
- 代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAX_N = 50;
int n,m,k[MAX_N];
int kk[MAX_N*MAX_N];
bool Binary_Search(int x)
{
int l=0,r=n;//这里要求r必须等于n,也就是说要多出一个无用的数组位,因为但x=k[n-1]时,l最终会等于n-1,如果r=n-1则会提前退出循环
while(r-l >= 1)
{
int i = (r+l)/2;
if(kk[i] == x) return true;
else if(kk[i] < x) l = i+1;
else r = i;
}
return false;
}
int main()
{
bool f = false;//判断是否能找到和为m得四个数字
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%d",&k[i]);
}
for(int c=0;c<n;c++)
{
for(int d=0;d<n;d++)
{
kk[c*n+d] = k[c] + k[d];
}
}
sort(kk,kk+n*n);//将数组排序
for(int a=0;a<n;a++)
{
for(int b=0;b<n;b++)
{
if(Binary_Search(m-k[a]-k[b]))
f = true;
}
}
if(f)
puts("yes");
else
puts("no");
return 0;
}
/*
n=3
m=9
k={1,3,5}
no
*/