<LeetCode OJ> 204. Count Primes

Description:

Count the number of prime numbers less than a non-negative number, n.



分析:

思路首先:一个数不是合数就是素数,合数更好推断呢!


合数:不论什么一个合数都能够表现为适当个素数的乘积的形式,
所以我们仅仅用小于sqrt(number)的素数去除要推断的数就可以,
由于合数在sqrt(number)以内一定有素数的质因子
比方要推断100以内的素数,仅仅需推断合数就可以。仅仅用10以内的2,3。5。7就够了,10000以内的数用100以内的素数推断足以。执行时间O(N)

class Solution {
public:
    
    int countPrimes(int n) {
        if(n<=2)
            return 0;
        
        basenum.reserve(10001);//预留空间
        basenum.push_back(2);
       
        int cnt=1;
        for (int  number=3; number < n; number++)//计算出n以内的素数个数
        {
            int flag = true;
            int tmp = static_cast<int>(sqrt(number));
            //推断是否是素数
            int j = 0;
            while (basenum[j] <= tmp)
            {
                if (number % basenum[j] == 0)
                { //此时合数
                    flag = false; 
                    break; 
                }
                j++;
            }
            if (flag)
            { 
                basenum.push_back(number);
                cnt++;
            }
        }
        return cnt;
    }
private:
    vector<int> basenum;//用于存储素数
};


这个问题是上海交通大学2008年的研究生面试题:

Prime Number

题目描写叙述:

Output the k-th prime number.

输入:

k≤10000

输出:

The k-th prime number.

例子输入:
3
7
例子输出:
5
17
我的答案:

#include "vector"  
#include <iostream>  
#include "fstream"
#include "algorithm"  
#include <stdio.h>
#include "string"
#include <cmath>
#include <cstdlib>
#include "map"
 
using namespace std;
 
vector<int> basenum;//用于存储素数
//素数推断法:不论什么一个合数都能够表现为适当个素数的乘积的形式,
//所以我们仅仅用小于sqrt(number)的素数去除要推断的数number就可以,
//比方要推断100以内的素数。仅仅用10以内的2,3,5,7就够了,10000以内的数用100以内的素数推断足以。
 
void initPrime()
{
    basenum.reserve(10001);//预留空间
    basenum.push_back(2);
    basenum.push_back(3);
    basenum.push_back(5);
    basenum.push_back(7);//先压入4个素数
    int  number=11;
     
    for (int i = 5; i <= 10000; number++)//计算出10000个素数
    {
        int flag = true;
        int tmp = static_cast<int>(sqrt(number));
        //推断是否是素数
        int j = 0;
        while (basenum[j] <= tmp)
        {
            if (number % basenum[j] == 0)
            { //此时合数
                flag = false; 
                break; 
            }
            j++;
        }
        if (flag)
        { 
            basenum.push_back(number);
            i++;
        }
    }
}
 
int main()
{
    int n;
    initPrime();
    while (cin>>n)
        printf("%d\n", basenum[n - 1]);
    return 0;
}
/**************************************************************
    Problem: 1040
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:1536 kb
****************************************************************/



以前写过的最糟糕的素数推断方法:

//思路首先:
//最朴素(糟糕)的方法
class Solution {
public:
    bool IsPrimeNum(int num)
    {
        if (num <= 1)
            return false;
        for (int i = 2; i <= num/2; i++)
        {
            if (num % i == 0)//一旦能够整除立刻返回他不是素数  
                return false;
        }
        return true;
    }
    int countPrimes(int n) {
        int cnt=0;
        int curNum=1;
        while(curNum<=n)
        {
            if(IsPrimeNum(curNum))
                cnt++;
            curNum++;
        }
        return cnt;
    }
};


小结:遇到存在对立角度的问题,能够考虑用还有一面来破解,而不拘泥于正面破解。

以后素数问题都直接推断合数问题就可以。


注:本博文为EbowTang原创,兴许可能继续更新本文。

假设转载,请务必复制本条信息!

原文地址:http://blog.csdn.net/ebowtang/article/details/50469592

原作者博客:http://blog.csdn.net/ebowtang

posted @ 2018-03-23 10:01  zhchoutai  阅读(266)  评论(0编辑  收藏  举报