【问题标题】:Need to make code efficient and reduce time complexity需要使代码高效并降低时间复杂度
【发布时间】:2021-08-29 12:54:56
【问题描述】:

给定一个范围 [ L , R ](包括两者),我必须告诉找到给定范围内两个素数之间的最大差异。给定范围可能有三个答案。

如果给定范围内只有一个不同的素数,那么这种情况下的最大差值为 0。

如果给定范围内没有素数,那么这种情况下的输出将为 -1。

例子:

Range: [ 1, 10 ]

The maximum difference between the prime numbers in the given range is 5.

Difference = 7 - 2 = 5


Range: [ 5, 5 ]

There is only one distinct prime number so the maximum difference would be 0.


Range: [ 8 , 10 ]

There is no prime number in the given range so the output for the given range would be -1.

输入格式 第一行输入包含测试用例的数量,T

接下来的 T 行每行由两个空格分隔的整数 L 和 R 组成

约束 1

2

这是我的代码:

    #include <stdio.h>
    int isprime(int n)
    {
        int i,c=0;
        for(i=1;i<n;i++)
        {
            if(n%i==0)
             c++;
        }
        if(c==1)
         return 1;
        else
         return 0;
    }
    
    int main()
    {
        int t; //testnumber
        scanf("%d",&t);
        for(int k=0;k<t;k++)
        {
         int l,r; //l=low or floor, r = highest range or ceiling;[l,r]
         scanf("%d%d",&l,&r);
         int n = r-l; //difference in range
         int a[n]; 
         int j=0;
         for(int i=l;i<=r;i++)
         {
             if(isprime(i)==1)
             {
                a[j] = i;
                j++;
             }
         }
         int d = a[j-1]-a[0];
         if(j==0)
          printf("%d\n",-1);
         else
          printf("%d\n",d);
        } 
        return 0;
    }

【问题讨论】:

  • 让代码高效运行实际上是任务的一部分。您提出的第一个想法通常不足以解决问题,其中一部分是时间限制。但只是说,您的isprime 循环只需要测试 odd 除数,即n 的平方根。它可以打破你找到一个因素的第一次。它不需要完成迭代。您可能会考虑的另一件事是制作一个素数列表,这样您就不必不断重复相同的计算。
  • 我投票结束这个问题,因为它属于:codereview.stackexchange.com
  • 您要学习的东西太多了。首先读取eratosthenes的筛子,然后对素数数组中的范围进行二分搜索。
  • 从isprime开始godbolt.org/z/hznbTcj5q

标签: c time time-complexity


【解决方案1】:

在论坛/堆栈上发帖或要求审核时,请尝试适当地命名您的变量。否则就很难看懂代码或者哪个变量的目的是什么。

我写了下面的代码希望你能理解我的实现。

#include <iostream>
#include <math.h>
using namespace std;

void isPrime(int num, int* primeNumber)
{
    if (num == 2)
    {
        *primeNumber = num; //2 is a prime number
        return;
    }
    if (num%2 == 0)
    {
        return; //num is an even number, so, not prime
    }
    int limit = sqrt(num);
    if (limit*limit == num)
    {
        return; //num is a square number, so, not prime
    }
    for (int i = 3; i <= limit; i=i+2)//to find if a number is prime or not, we only have to divide it from 2 to sqrt(num).
    {          //i=i+2 skips even number, cause already checked if num is even or not.
        if (num % i == 0)
        {
            return; //`num` is divisible by i, so, not prime
        }
    }
    *primeNumber = num; //no divisible number found. so, num is prime.
}

int main() 
{
    int testNumber;
    cout<< "Enter testNumber: ";
    cin>> testNumber;

    for (int i = 0; i < testNumber; ++i)
    {
        int  newLow, low, high, lowestPrime = 0, highestPrime = -1;
        cin>> low>> high;
        newLow = low;
        if (low == high)
        {
            cout<<"0\n";
            continue;
        }

        for (int j = low; j <= high; ++j)//find the lowest prime
        {
            isPrime(j, &lowestPrime);
            if (lowestPrime != 0)//if lowest prime found, lowestprime will no longer be 0
            {
                //cout<<"lowest prime: "<<lowestPrime<<endl;
                newLow = j; //there is no prime number between low...newLow
                break;
            }
        }

        for (int j = high; j >= newLow; j--)//find highest prime
        {
            isPrime(j, &highestPrime);
            if (highestPrime != -1)//if highest prime found, highestprime will no longer be -1
            {
                //cout<<"highest prime: "<<highestPrime<<endl;
                break;
            }
        }

        cout<<highestPrime - lowestPrime<<"\n";
    }

    return 0;
}

【讨论】:

  • 请不要提供挑战问题的代码:直接在网站上提交,作为您自己的解决方案。有很多关于素数算法的文章,OP 可以轻松研究这些算法。你所做的只是让人们可以复制/粘贴并将其作为自己的作品提交,并幻想他们已经取得了一些成就。它甚至不是用 C 语言编写的。
  • 我希望他只是了解实现。他是新手,所以,我认为让他做研究而不是回答问题可能会吓跑他。这就是为什么我专注于 cmets 而不是语言。
【解决方案2】:

此任务不需要任何特殊算法(除了检查数字是否在 O(sqrt(N)) 中为素数)即可有效解决。想想素数,它们在某个范围内(例如从 1 到 100 的范围内)的频率是多少,出现的一些“模式”是什么。现在,如果我正确理解了这个任务,您需要在last_prime_on_range - first_prime_on_range 的范围内找到最大的素数差异,从这个和之前的观察中,您可以轻松设计一个有效的算法。

剧透:

你不需要检查整个范围,从 L 到 L+100 就足够了 从 R 到 R-100,显然如果 L+100>R 你可以从 L 到 R。 如果你想确保你可以从 L 到 L+1000 和从 R 到 R-1000,因为它不会对时间复杂度产生太大影响。 此外,在找到素数时添加break; 也可以解决问题。 请注意,质数之间的差距不能保证低于 100/1000,但对于给定的范围,检查高达 1000 就足够了。

现在如果您需要检查范围内的所有素数,您应该了解Sieve Of Eratosthenes

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-28
    相关资源
    最近更新 更多