算法的复杂性是
O(n(logn)(loglogn))
位操作。
你是如何达到的?
复杂性包括loglogn
术语告诉我某个地方有sqrt(n)
。
假设我在前100个数字(n = 100
)上运行筛子,假设将数字标记为复合需要恒定时间(数组实现),我们使用mark_composite()
的次数将是
n/2 + n/3 + n/5 + n/7 + ... + n/97 = O(n^2)
要查找下一个素数(例如,在越过7
的倍数的所有数字后跳转到5
,操作数将为O(n)
。
因此,复杂性将是O(n^3)
。 你同意吗?
答案 0 :(得分:105)
你的n / 2 + n / 3 + n / 5 + ... n / 97不是O(n),因为术语数不是常数。 [编辑后编辑:O(n 2 )上限过松。]松散的上限是n(1 + 1/2 + 1/3 + 1/4 + 1 / 5 + 1/6 + ... 1 / n)(所有数字到n的倒数之和),即O(n log n):见Harmonic number。更合适的上限是n(1/2 + 1/3 + 1/5 + 1/7 + ...),即素数到n的倒数之和,即O(n log log n)。 (请参阅here或here。)
“找到下一个素数”位只有O(n)整体,amortized - 您将继续前进,在总计中仅查找下一个数字n次,而不是每一步。所以这个算法的整个部分只需要O(n)。
因此,使用这两个,你得到O(n log log n)+ O(n)= O(n log log n)算术运算的上界。如果你计算位操作,因为你处理的数字最多为n,它们有大约log n位,这是log n的因子进来,给出O(n log n log log n)位操作。
答案 1 :(得分:8)
复杂性包括loglogn术语告诉我某个地方有一个sqrt(n)。
请注意,当您在筛选时找到素数P
时,您不会在当前位置+ P
开始交叉数字;你实际上开始在P^2
处勾选数字。所有P
小于P^2
的倍数都将被之前的素数划掉。
答案 2 :(得分:7)
n/i
步骤,其中i
为prime =>整体
复杂度为sum(n/i) = n * sum(1/i)
。根据泛音
系列sum (1/i)
其中i
为素数为log (log n)
。在
总计,O(n*log(log n))
。我认为可以通过将n
替换为sqrt(n)
来优化上层循环,这样整体时间复杂度将为O(sqrt(n)loglog(n))
:
void isprime(int n)
{
int prime[n],i,j,count1=0;
for(i=0;i<n;i++)
{
prime[i]=1;
}
prime[0]=prime[1]=0;
for(i=2;i<=n;i++)
{
if(prime[i]==1)
{
printf("%d ",i);
for(j=2;(i*j)<=n;j++)
prime[i*j]=0;
}
}
}
答案 3 :(得分:1)
int n = 100;
int[] arr = new int[n+1];
for(int i=2;i<Math.sqrt(n)+1;i++) {
if(arr[i] == 0) {
int maxJ = (n/i) + 1;
for(int j=2;j<maxJ;j++)
{
arr[i*j]= 1;
}
}
}
for(int i=2;i<=n;i++) {
if(arr[i]==0) {
System.out.println(i);
}
}
对于所有 i>2,Ti = sqrt(i) * (n/i) => Tk = sqrt(k) * (n/k) => Tk = n/sqrt(k)
当 k=sqrt(n) => n[ 1/sqrt(2) + 1/sqrt(3) + ...] = n * log(log(n)) => O(nloglogn) 时循环停止
答案 4 :(得分:0)
请参阅上面的解释,内部循环是直到sqrt(n)的所有质数的谐波和。因此,的实际复杂度为O(sqrt(n)* log(log(sqrt(n))))