我使用了这种方法。
但是当数值非常大(~10 ^ 9)时,这种天真的方法看起来效率很低,因为GCD的时间复杂度将取决于数字的大小。对于非常大的N值也是不可行的。 还有其他更好的解决方法吗?
答案 0 :(得分:0)
我认为没有一种有效的算法。
你总是可以使用启发式和简单的方法来解决这个问题。
平均而言,对于大多数阵列,这对数字将类似于a,b(a
因此,平均而言,LCM不会非常大并且与阵列的元素类似。
所以,Idea就是对数组进行排序,然后首先尝试使用较小的a,b。当b
> lcm_so_far
。
由于
答案 1 :(得分:0)
对于大量数字,有效实现欧几里德算法(https://en.wikipedia.org/wiki/Euclidean_algorithm#Algorithmic_efficiency)以找到GCD是我能想到的最佳路线。没有用于素数分解的快速通用算法,因此使用它来减少问题将无助于运行时间。我不知道有任何快速减少会对此有所帮助。
解决大N问题,我认为这是其他人所得到的:
可以对此进行其他优化(例如不在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)):
#Best case for remaining pairs
if i < len(a) - 1 and a[i + 1] >= cur_lcm: break
for j in range(i + 1, len(a)): #Starting at i + 1 avoids duplicates
if a[j] >= cur_lcm: break #Best case for remaining pairs
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)): #Starting at i + 1 avoids duplicates
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)]
#Only print the list if it's relatively short
if len(a) < 20: print a
#Try all pairs
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)