给定数字n,找到最接近它的质数,最大偶数

时间:2019-02-18 11:31:04

标签: python python-3.x

我很难找到最接近偶数最大的给定整数n的质数。下面的代码有效并通过了所有示例测试。但是,当数字太大时,它就会超时。谁能建议我如何优化它?

"Given xpath expression "//div[@class=inner-results firma]" is invalid: SyntaxError: The expression is not a legal expression."

测试1的期望值为887
测试2的期望值为1201
测试3的期望值为8887

编辑: 根据建议,由于一个数字中最大质数的总位数总是比总数字少一,因此,我只保留了那些长度与给定整数N相同的数字。足够。对于素数检查,我在isPrime Function for Python Language

使用了选定的答案
from collections import defaultdict


def is_prime(n):
    first, i = 1, 2
        if n <= first:
            return False
    while i <= (n**0.5):
        if n % i == 0:
            return False
        i += first
    return True


def highest_prime(n):
    dd = defaultdict(int)
    nums = [str(x) for x in reversed(range(n)) if is_prime(x)]
    is_even = (lambda x: x % 2 == 0)
    for outer in nums:
        for inner in outer:
            if is_even(int(inner)):
                dd[outer] += 1
    return max(dd, key=lambda x: dd[x])


if __name__ == "__main__":
    print(highest_prime(1000))
    print(highest_prime(1210))
    print(highest_prime(10000))

还有其他建议吗?谢谢!

3 个答案:

答案 0 :(得分:2)

有很多非常聪明的方法可以测试一个数字是否为质数(或者至少聪明的方法可以校正一个非常大的N),但是在这种情况下,当您计算所有质数直到某个数字时,就可以使用以前的质数,仅检查它们是否为因数:

fromList (a:as) = a :| as

如果您正在寻找比此方法更有效的方法(由于该方法仍然消耗资源,并且当花费数千万美元时仍会花费很长时间),最好的选择是找到一个有效的现有方法像提到的Rabin-Miller素数测试一样的素数测试

答案 1 :(得分:1)

您应该考虑两个主要的优化领域。

首先要确保我们的素数检查正确。从Source采取聪明的暴力破解方法,您基本上只需要检查6n - 16n + 1中从1到数字平方根的所有n即可确定是素数还是素数。不。 (因为6n + 26n + 4是偶数,并且6n + 3被3整除)。我在下面的is_prime(n)函数中添加了解释。

真正起作用的第二个方面是确保始终跟踪“偶数位的最佳结果”。这个想法很简单:素数为n的质数最多可以有n-1个偶数,但素数2除外。考虑到这一点,我们只需要确保可以找到可能的“最佳情况”,而不是将所有素数累加到给定的数字n,我们只是找到适合我们最佳情况的最高素数,从大到小。因此,我有highest_prime_optimized(n)和评论。我最初计划将其时间与原始功能进行比较,但是一旦原始功能运行了一分钟,我便决定将其终止。这应该胜过测试。

import time

def is_prime(n):
    #base cases handling
    if n == 2 or n == 3: return True #handles 2, 3
    if n < 2 or n%2 == 0: return False #handles 1 and even numbers
    if n < 9: return True #since 1, 2, 3, 4, 6 and 8 are handled, this leaves 5 and 7.
    if n%3 == 0: return False #handles multiples of 3
    r = int(n**0.5) #only check upto square root
    f = 5 #start from 5
    while f <= r:
        #print ('\t', f)
        if n%f == 0: return False #essentially checks 6n - 1 for all n.
        if n%(f+2) == 0: return False #essentially checks 6n + 1 for all n.
        f +=6 #incrementing by 6.
    return True

def max_even_digits_in_prime(n):
    return (len(str(n)) - 1) or 1 

def count_of_even_digits(n):
    count = 0
    for i in str(n):
        count+= (int(i) % 2 == 0)
    return count

def highest_prime_optimized(n):
    best_case = (0, 0) #keeps track of highest best case number seen[1], and its count of even digits[0]
    for x in range(n, 1, -1): #iterate in the reverse direction
        #print(x)
        if is_prime(x): #proceed for prime numbers
            even_digits = count_of_even_digits(x)
            max_even_digits = max_even_digits_in_prime(x)
            if best_case[0] < even_digits: #update best number seen so far
                best_case = (even_digits, x)
            if max_even_digits == best_case[0]: #best case answer, your work is done. No need to look for more numbers.
                print(best_case)
                return (best_case[1])

if __name__ == "__main__":
    print(highest_prime_optimized(1000))
    print(highest_prime_optimized(1210))
    print(highest_prime_optimized(10000))
    start = time.time() 
    result = highest_prime_optimized(5000000)
    print(result, time.time() - start)
    #Output: 4888889 0.5920031070709229

答案 2 :(得分:0)

使用“ Eratosthenes筛子”算法,该算法生成小于N的素数。

希望这可以解决您的问题。

时间复杂度:O(n * log(log(n)))

参考:     https://www.geeksforgeeks.org/sieve-of-eratosthenes/