牛牛的公因数
30分解法
用i遍历所有可能的答案(1-1e3),用j遍历n个数,每当a[j]%i==0时给答案i的权值++,最后从小到大扫一遍所有可能答案的权值,每遇到k的都更新ans=i即可,最后将ans返回,时间复杂度o(n^2),空间复杂度o(n);
100分做法
介绍两种做法,一种时间复杂度的,一种时间复杂度
的
1.时间复杂度
,空间复杂度
的做法:
对于每个数,我们可以算它对所有因子的影响,只需要从$1到\sqrt{n}枚举因子即可,比较需要注意的是,对于平方数,它的开方因子贡献只有1,需要特判,代码如下:
int cnt[100005];
class Solution {
public:
/**
*
* @param arr int整型vector
* @param k int整型
* @return int整型
*/
int Maximumnumber(vector<int>& arr, int k) {
// write code here
int i,j,n=arr.size();
for(i=0;i<n;i++)
{
for(j=1;j*j<arr[i];j++)
{
if(arr[i]%j==0)
{
cnt[j]++;
cnt[arr[i]/j]++;
}
}
if(j*j==arr[i])cnt[j]++;
}
int ans=1;
for(int i=100000;i>=2;i--)
{
if(cnt[i]>=k){ans=i;break;}
}
return ans;
}
};2.时间复杂度
,空间复杂度
的做法:
可以先统计每个数的个数,然后对于每个数做为因子的贡献,是他所有倍数个数的和。一层循环遍历数的范围(1-1e5),第二层循环遍历每个数,然后翻倍这个数,第二层循环的时间为1/n+2/n+...+n/n,是调和级数,在n足够大的情况下时间复杂度趋近logn,所以总的时间复杂度当然,本题数据范围较小,在两做法时间上几乎看不出差别,但如果数据范围到了1e6,经测试第一种做法大概需要9-10s,第二种做法只需要1s左右,还是有显著的时间优势的。代码如下:
int num[100005];
int cnt[100005];
class Solution {
public:
/**
*
* @param arr int整型vector
* @param k int整型
* @return int整型
*/
int Maximumnumber(vector<int>& arr, int k) {
// write code here
for(int i=0;i<arr.size();i++)num[arr[i]]++;
for(int i=2;i<=1e5;i++)
{
for(int j=i;j<=1e5;j+=i)
{
cnt[i]+=num[j];
}
}
int ans=1;
for(int i=1e5;i>=2;i--)
{
if(cnt[i]>=k){ans=i;break;}
}
return ans;
}
};
