我是编程的新手,而我的一位朋友建议我应该对项目Euler进行练习以使其更好。我在问题3上遇到了一个问题:
“13195的主要因素是5,7,13和29. 600851475143的最大主要因素是什么?”
现在这是我的解决方案:
class Program
{
static void Main(string[] args)
{
long number = 600851475143;
bool prime = true;
for (long i = 3; i <= number; i++)
{
for (long n = 2; n < i; n++)
{
if (i % n == 0)
{
prime = false;
break;
}
}
if (prime)
{
if (number % i == 0)
{
Console.WriteLine(i);
}
}
prime = true;
}
Console.ReadKey();
}
}
现在,虽然我确实得到了正确的答案(这是6857),但我发现我的方法非常低效。如果您将运行我的代码,您将看到它仍将在超过2分钟之后运行...我的问题是如何为此编写更高效/更快的代码?
答案 0 :(得分:5)
我的问题是如何为此编写更有效/更快的代码?
这是错误的问题。或者说,这是一个不成熟的问题。
要问的正确问题是:
快速制作错误的程序使您能够更快地得到错误的答案,这不是一个改进。 更快地制作组织糟糕的程序非常困难,所以先组织好。
让我们开始为您的计划做一个小但非常重要的改进:我们注意到#34;这件事是不是很重要?&#34;可以由助手清楚地表示:
class Program
{
static bool IsPrime(long i)
{
for (long n = 2; n < i; n++)
{
if (i % n == 0)
return false;
}
return true;
}
static void Main(string[] args)
{
long number = 600851475143;
for (long i = 3; i <= number; i++)
{
if (IsPrime(i))
Console.WriteLine(i);
}
Console.ReadKey();
}
}
看看那里发生了什么。 您的计划突然变得更容易理解。 IsPrime做什么?它会告诉您整数是否为素数。主循环有什么作用?它打印出3和数字之间的所有素数。
现在,重新开始。 该计划的每个部分都是正确的吗?当IsPrime
给定时,true
会返回1
,但通常不会被视为素数。 修复错误。您希望辅助方法可靠。 确保您的帮助方法完全按照他们在锡上的说法进行操作。写测试!因为您希望确保在更改这些方法以使其更快时,您不会意外地使它们不正确。
现在我们既有正确又有条理,我们可以开始优化。你能想到让IsPrime更快的方法吗?肯定的是:
i
的平方根。 (请注意,n * n <= i
比n <= Sqrt(i)
)你能想到其他方法让它更快吗?
但关键是妥善整理您的计划。一旦你有一个组织良好的程序,你可以在更高的层次上推理,你可以找到并消除缓慢的部分。
答案 1 :(得分:3)
首先,您使用的算法是为了知道数字是否为素数,效率非常低(order(n2)),您可以改进函数的顺序,返回数字是否为素数
要确定某个数字是否为素数,您需要检查它是否不能被任何小于n的数字整除。
你只需要考虑高达√n的因子,因为如果n可以被某个数p整除,那么n = p×q,因为p≤q,你可以推导出p≤√n。请注意,您正在考虑小于n而不是小于√n的数字因子。
也许这个类似的问题可以帮到你,“下面最大的素数是什么”。
解决问题的最佳方法,正在使用Eratosthenes筛选。 (的 https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes 强>)
这是使用Erastosthenes筛子的伪代码。
public int primes(int n) {
boolean[] isPrime = new boolean[n];
for (int i = 2; i < n; i++) {
isPrime[i] = true;
}
// Loop's ending condition is i * i < n instead of i < sqrt(n)
// to avoid repeatedly calling an expensive function sqrt().
for (int i = 2; i * i < n; i++) {
if (!isPrime[i]) continue;
for (int j = i * i; j < n; j += i) {
isPrime[j] = false;
}
}
int count = 0;
for (int i = 2; i < n; i++) {
if (isPrime[i]) count++;
}
//return the max prime
int maxPrime = 1;
for(int i = 0; i < isPrime.count; i++){
if(isPrime[i]){
maxPrime = i;
}
return maxPrime;
}
}
答案 2 :(得分:1)
我写了一个方法,它将为您提供所有主要因素,以及其中最大的因素。我的代码正在运行,您可以查看它:
public void PrimeFactor1(long n)
{
List<int> sList = new List<int>();
long temp = 1;
for (int i = 2; i <= n; i++)
{
if ((n % i) == 0)
{
temp = n / i;
sList.Add(i);
i = 1;
n = temp;
}
}
string arr = string.Join(",", sList.ToArray());
Console.Write(arr);
Console.WriteLine(".");
Console.WriteLine("The Biggest Prime number is: {0}", sList.Max());
}
答案 3 :(得分:0)
如果您要处理许多Project Euler问题,那么您需要很好地实施Eratosthenes筛选。您的Eratosthenes类的两个有用方法是nextPrime(int p)
和previousPrime(int p)
,它们分别返回下一个和下一个最低素数。
ETA:伪代码编辑为错误。遗憾。