老师,关于求质数复杂度以及逻辑的问题

来源:2-3 简单的复杂度分析

张婧仪

2019-11-17

老师,您在2-3节的最后分析了判断质数的复杂度,于是我写了一个求n以内质数的算法(LeetCode204号问题)。我想问的是第二重for循环的时间复杂度怎么求?代码如下:

public int countPrimes2(int n) {
        if(n==0||n==1||n==2)
            return 0;
        boolean[] primes=new boolean[n];
        Arrays.fill(primes,true);
        int size= (int) Math.sqrt(n);
        for(int i=2;i<=size;i++){
            if(primes[i]) {
                //这重for循环的时间复杂度怎么求?
                for (int j = i * i; j < n; j += i) {
                    primes[j] = false;
                }
            }
        }
        int count=0;
        for(int i=2;i<n;i++){
            if(primes[i])
                count++;
        }
        return count;
    }
写回答

1回答

liuyubobobo

2019-11-18

筛素数法的时间复杂度分析理论性太强了,原因就在于你说的这重循环,是一个不定循环(循环次数不固定)


这类时间复杂度分析,严谨的要列出数学表达式,求出其上界。有点儿类似 heapify 的过程为什么是 O(n) 的而非 O(nlogn) 的。

严谨的这个时间复杂度分析已经远远超过这个课程的范畴了,并且,我向你保证,任何面试或者笔试都不会考察这个内容。整体,是在求如下 T(n) 在 n 趋近于无穷时候的积分。

//img.mukewang.com/szimg/5dd2048c095413c800800057.jpg

求解这个积分需要 Mertens 定理。最终结果是 nlog(logn)。


如果感兴趣可以参考这篇论文:https://research.cs.wisc.edu/techreports/1990/TR909.pdf

关于 Mertens 定理,可以参考这里:https://arxiv.org/pdf/math/0504289.pdf 


不过,对于这个代码,粗糙的分析,说外层循环 sqrt(n) 次,内层循环最多 是 O(n)的,所以整体是 O(nsqrt(n)) 的,但肯定比这个低(因为内层循环次数越来越少)。

同时,因为内层循环最少是 n/sqrt(n),所以整体肯定比 O(n) 高。介于 O(n) ~ O(nsqrt(n)) 之间。

这个分析结果,对于工程师来说,已经足够了。


加油。

1
1
张婧仪
非常感谢!
2019-11-18
共1条回复

玩转算法面试-- Leetcode真题分门别类讲解

课程配套大量BAT面试真题,高频算法题解析,强化训练

7446 学习 · 1159 问题

查看课程