对于大量数字,我认为一个高效的欧几里得算法实现(https://en.wikipedia.org/wiki/Euclidean_algorithm#Algorithmic_efficiency)来寻找最大公约数是我能想到的最佳方法。没有快速通用的分解主因数的算法,因此使用它来减少问题不会帮助运行时间。我不知道有任何快速缩小范围的方法可以帮助解决这个问题。
针对大 N,我认为这就是其他人所说的:
1. 对数组进行排序
2. 从最小值开始计算最小公倍数(例如使用欧几里得算法计算最大公约数),并使用短路:一旦剩余配对的LCM不能小于迄今为止找到的最佳值,则停止处理。请注意,在排序集合中,对于两个数字b和c,b < c,LCM的下界是(b * c) / b = c(当b整除c时发生)。请参见以下工作代码(short_lcm版本)。
还有其他优化可以应用于此(例如不要在Python中编写它:)),但这证明了算法的改进。
import fractions
def lcm(a, b):
return abs(a * b) / fractions.gcd(a, b)
def short_lcm(a):
a = sorted(a)
iterations = 0
cur_lcm = lcm(a[0], a[1])
first = a[0]
second = a[1]
for i in range(0, len(a)):
if i < len(a) - 1 and a[i + 1] >= cur_lcm: break
for j in range(i + 1, len(a)):
if a[j] >= cur_lcm: break
iterations += 1
test = lcm(a[i], a[j])
if test < cur_lcm:
cur_lcm = test
first = a[i]
second = a[j]
if iterations < 1: iterations = 1
print("Lowest LCM pair is (%d, %d): %d. Found in %d iterations" % (
first, second, cur_lcm, iterations))
def long_lcm(a):
iterations = 0
cur_lcm = lcm(a[0], a[1])
first = a[0]
second = a[1]
for i in range(0, len(a)):
for j in range(i + 1, len(a)):
iterations += 1
test = lcm(a[i], a[j])
if test < cur_lcm:
cur_lcm = test
first = a[i]
second = a[j]
print("Lowest LCM pair is (%d, %d): %d. Found in %d iterations" % (
first, second, cur_lcm, iterations))
if __name__ == '__main__':
from random import randint
import time
a = [randint(1, 1000) for r in xrange(100)]
if len(a) < 20: print a
start = time.clock()
long_lcm(a)
print "Slow version time: %f\n" % (time.clock() - start)
start = time.clock()
short_lcm(a)
print "Fast version time: %f" % (time.clock() - start)
n
的最大范围是多少? - Kaidul