【问题标题】:How to find the nearest prime number in an array, to another number in that array?如何在数组中找到与该数组中另一个数最近的素数?
【发布时间】:2014-11-29 04:23:09
【问题描述】:

我想找出与数组中任何其他数字最近的素数(存在于该数组中)?
示例:

list a -> [1,2,4,6,8,12,9,5,0,15,7]

所以最接近4 的素数将是2,如果是15,它将是7。在这里,我假设列表中的每个元素都是不同的。
我花了几个小时但无法解决,有没有efficient 的方法来解决这个问题?

【问题讨论】:

  • 列表中可能的最大数字是多少?
  • 定义高效。 . .并且该方法可能取决于我们正在谈论的数字数量以及它们可以有多大。 . .
  • 定义最近的 - 素数可以大于或小于给定的数字(甚至等于?)。在您的示例中,最接近 12 的素数是什么 - 是 7 还是 15?
  • @TonySuffolk66 -- 15 不是质数,如果我理解这个问题,我认为与 12 最接近的质数是 5 。 . .
  • 哇!当然 15 不是素数-doh !仍然需要明确定义最接近 - 绝对值最近 - 原始列表中的距离最近或其他解释?

标签: python algorithm list python-2.7


【解决方案1】:

首先,您需要一个好的素数检查器。 Wikipedia has an implementation -- 根据python版本等可能会进一步优化。

现在,列出所有素数的索引:

indices = [i for i, val in enumerate(data) if is_prime(val)]

接下来,选择一个任意数字并找到它的索引(或者不是任意...)。

n = random.choice(data)
idx = data.index(n)

我们就快到了...将您的方法一分为二,找出n 的索引在索引列表中的位置。

indices_idx = bisect.bisect_left(indices, idx)

现在,要确定更接近的数字是在左侧还是右侧,我们需要查看这些值。

# Some additional error handling needs to happen here to make sure that the index
# actually exists, but this'll work for stuff in the center of the list...
prime_idx_left = indices[indices_idx - 1]
prime_idx_right = indices[indices_idx]

最后,找出哪个索引更接近并提取值:

if (idx - prime_idx_left) <= (prime_idx_right - idx):
    closest_prime = data[prime_idx_left]
else:
    closest_prime = data[prime_idx_right]

请注意,我在假设您将一遍又一遍地使用相同的列表的情况下进行了此操作。如果你不是,你最好这样做:

  • 找到您感兴趣的号码的索引。
  • 找到右边第一个素数的索引(如果存在)
  • 找到左边第一个素数的索引(如果存在)
  • 检查哪个更近

例如

def find_idx_of_prime(lst, start_idx, stop_idx, dir):
    for ix in xrange(start_idx, stop_idx, dir):
        if is_prime(lst[ix]):
            return ix
    return dir*float('inf')

idx = data.index(number)
left_idx = find_idx_of_prime(data, idx, 0, -1)
right_idx = find_idx_of_prime(data, idx, len(data), 1)
prime_idx = left_idx if idx - left_idx < right_idx - idx else right_idx
prime_value = data[prime_idx]  # raises TypeError if no primes are in the list.

【讨论】:

  • +1。您可以找到max(lst) 并使用埃拉托色尼筛法生成一组小于max(lst) + 1 然后isprime = primes.__contains__ 的所有素数。 The code is very simple e.g., sieve_of_eratosthenes(limit) 如果max(lst) 与len(lst) 相比可能更大,则可以使用直接素数测试,例如you've linked。如果max(lst) 非常大,则应使用概率方法,例如 Miller-Rabin 素数检验。
【解决方案2】:

下面是埃拉托色尼筛法的一个相当有效的实现,可以与 mgilson 的代码结合使用。但正如 J.F. Sebastian 所说,如果列表中的数字非常大,和/或列表的长度很短,使用预先计算的素数表可能效率不高。

def primes(n):
    ''' Return a boolean list of all primes < n '''
    s = [False]*2 + [True]*(n-2)
    for i in xrange(2, int(n**0.5) + 1):
        if s[i]:
            s[i*i : n : i] = [False] * (1 + (n - 1)//i - i)
    return s

你会这样使用它:

a = [1,2,4,6,8,12,9,5,0,15,7]
is_prime = primes(max(a) + 1)

然后将mgilson的find_idx_of_prime()函数改成:

def find_idx_of_prime(lst, start_idx, stop_idx, dir):
    for ix in xrange(start_idx, stop_idx, dir):
        if is_prime[lst[ix]]:
            return ix
    return dir*float('inf')

【讨论】:

  • 糟糕!我最好将 / 更改为 // 以便它在 Python 3 上正常工作。:)
猜你喜欢
  • 2020-01-17
  • 1970-01-01
  • 2022-11-16
  • 2016-12-28
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
  • 1970-01-01
  • 2014-01-13
相关资源
最近更新 更多