题目要求:输出比一个非负数字N小的prime的个数;
素数: 是只有两个正因子(1和自己)的自然数;最小的素数是2;
合数: 比1大但不是素数的数称之为合数;
0和1不是素数也不是合数;
IsPrime()方法: 能够被小于n的任何整数整除->false; else-> true
思路1 暴力解法
结论: 测试用例:499979 超时;
public int CountPrimes(int n) {
//Console.WriteLine(IsPrime(2));
//Console.WriteLine(IsPrime(3));
if (n == 0) return 0;
if (n == 1) return 0;
int count = 0;
for (int i = 2; i < n; i++)
{
if (IsPrime(i))
count++;
}
return count;
}
/// <summary>
/// 如果n能被小于n的数字整除,非prime
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
private bool IsPrime(int n)
{
if (n == 0)
return false;
if (n == 1)
return false;
if (n == 2)
return true;
for (int i = 2; i < n; i++)
{
if (n % i == 0)
return false;
}
return true;
}
结论: 测试用例:499979 超时;
思路2
如果一个数是另一个数的倍数,那这个数肯定不是素数。利用这个性质,我们可以建立一个素数数组
1 从2开始将素数的倍数都标注为不是素数
2 第一轮将4、6、8等表为非素数
3 然后遍历到3,发现3没有被标记为非素数,则将6、9、12等标记为非素数,一直到N为止
4 再数一遍素数数组中有多少素数。
public int CountPrimes(int n) {
bool[] prime = new bool[n];
//全标记为素数
for(int i=0;i<prime.Length;i++)
{
prime[i] = true;
}
for (int i = 2; i < n; i++)
{
if (prime[i])
{
// 将i的2倍、3倍、4倍...都标记为非素数
//初始值为:i*2; 边界条件j<n; j=j+i; 保障j每次加i,就是2,3,4倍
for (int j = i * 2; j < n; j = j + i)
{
prime[j] = false;
}
}
}
int count = 0;
for (int i = 2; i < n; i++)
{
if (prime[i]) count++;
}
return count;
}