我使用了这种方法。
- 找到所有可能的nC2 对n 个数。
- 然后通过计算他们的GCD 并将两个数字的乘积除以他们的 GCD 来单独找到他们的LCM 。
- 还维护了一个变量,其中包含到目前为止计算的最小 LCM 值并最终输出它。
但是当数值非常大(~10^9)时,这种幼稚的方法似乎效率低下,因为 GCD 的时间复杂度将取决于数字的大小。对于非常大的 N 值也是不可行的。还有其他更好的方法来解决这个问题吗?
我使用了这种方法。
但是当数值非常大(~10^9)时,这种幼稚的方法似乎效率低下,因为 GCD 的时间复杂度将取决于数字的大小。对于非常大的 N 值也是不可行的。还有其他更好的方法来解决这个问题吗?
我不认为有一个有效的算法。
你总是可以使用启发式和简单的,这肯定会解决这个问题。
平均而言,对于大多数数组,这对数字将类似于 a,b(a<b),其中 LCM(a,b) ~ O(b),即 a 的大部分因子都包含在 b 中,因此 LCM 大约为的 O(b)。
因此,平均而言,LCM 不会很大并且与数组的元素相似。
所以,想法是对数组进行排序,然后按升序先尝试较小的 a,b。当b
> lcm_so_far
。
谢谢
对于大量数字,欧几里得算法 ( https://en.wikipedia.org/wiki/Euclidean_algorithm#Algorithmic_efficiency ) 的有效实现是我能想到的最佳途径。没有快速、通用的素数分解算法,因此使用它来减少问题无助于运行时间。我不知道有任何快速减少会对此有所帮助。
针对大 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)