如何改进此代码以提高时间效率?对于循环,素数



任务取自www.codewars.com

素数的间隔不是规则的。例如从2到3步骤是1。从3到5,步长为2。从7点到11点是4点。在2和50之间,我们有以下两对2步素数:

3,5-5,7,-11,13,-17,19,-29,31,-41,43

我们将编写一个带有参数的函数步骤:

g(整数>=2(,表示我们正在寻找的步骤,

m(整数>=2(,其给出搜索的开始(包括m(,

n(整数>=m(,其给出搜索的结束(包括n(

在上面的例子中,步骤(2,2,50(将返回[3,5],它是第一对介于2和50之间,具有2步。

所以这个函数应该返回两个素数的第一对在极限m,n之间间隔一个g阶,如果这些g阶素数数字以其他方式存在nil或null或None或Nothing或[]或";0;或{0、0}或0 0(取决于语言(。

示例:步骤(2,5,7(->[5,7]或(5,7(或{5,7}或";57〃;

步骤(2,5,5(->零或。。。或Ocaml中的[]或C++中的{0,0}

步骤(4130200(->[163167]或(163167(或{163167}

请参阅";测试";

备注:([193197]也是这样一个介于130和200之间的4阶素数但这不是第一对(。

步骤(6100110(->[101107]尽管在101之间有素数以及107,其为103;对101-103是2步。

这是我的解决方案,它工作得很好,需要比测试更多的时间,但是,我正在尝试优化此代码,以使其更节省时间

def step(g,m,n):
count = 0
list= []
list2 = []
for num in range(m,n+1):
if all(num%i!=0 for i in range(2,num)):
count += 1
list.append(num)


for k in list:
for q in list:
if (q-k) > 0:
if (q-k) == g:
list2.append(k)
list2.append(q)


if not list2:
return 
else:
return  [list2[0],list2[1]]

如果您有任何建议,甚至是示例代码,我将不胜感激

首先,从不使用关键字作为变量

为了找到更好的方法,你需要考虑你方法中的缺陷。

  1. 您正在迭代所有的数字来确定素数
  2. 您正在遍历O(n**2(中的列表,以确定是否存在具有所需差异的对
  3. 你的素数计算算法不是最优的

对于第一点,甚至不需要找到给定范围内的所有素数,因为您的任务是找到具有所需差异的第一对。所以,如果你找到数字a是素数,a + g也是素数,那么你已经找到了解。

对于第二点,您可以简单地遍历列表,并检查if (k + g) in list以确定是否找到了对。

对于第三点,您可以在维基百科页面本身上找到一个最佳实现。如果您能够理解逻辑,那么您可以非常容易地自己编写实现。

因此,将最佳素数检查实现与单循环迭代相结合,可以很容易地编写解决方案,如下所示。

from functools import lru_cache
@lru_cache(None)
def is_prime(n):
if n <= 3:
return n > 1
if n % 2 == 0 or n % 3 == 0:
return False
i = 5
while i ** i <= n:
if n % i == 0 or n % (i + 2) == 0:
return False
i += 6
return True

def step(g, m, n):
for i in range(m, n + 1 - g):
if is_prime(i) and is_prime(i + g):
return [i, i + g]
return

对于step(4, 130, 200)的1000000次迭代,此实现仅用了1.32秒。正如您所看到的,一旦实现了is_prime函数,逻辑就非常简单。

最新更新