做练习的时候碰到了这种问题,对于两个数的求法我们可以用辗转相除法
return x if y==0 else gck(y,x%y)
求出它们的最大公因数,
然后再用两数之积/最大公因数
return x*y/gck(x,y)
求出最小公倍数,那么对于多个数字,我们可不可以仿照这种方法来求解呢?
分析
如果把多个数字看作一个列表,我们要做的就是对其相邻的两个元素进行一个最小公倍数的运算,将得到的结果与下一位数字再进行运算,依此类推。
但是这样进行的话可能会有一些问题,举例子来说
[1,2,3,4,5]
正常推理下最小公倍数为60
但按照刚才的方法来做,其结果依次为
[2,3,4,5]
[6,4,5]
[24,5]
[120]
为什么会这样呢?
究其原因,是因为列表中的[2,4]这两个存在倍数关系,他们的最小公约数为2,但在列表中的公约数为1,致使所得结果多乘了2,所以,我们要先对列表中的数字进行一些处理
列表处理
for i in range(len(x)): #对列表元素进行操作
if x[i] == 1: #如果列表元素为1,不进行任何操作
continue
else:
#新建一个列表,若其中没有任何元素,将x[]中第一个不为1的元素插入
if len(y) == 0:
y.append(x[i])
for j in range(len(y)): #对列表y[]进行处理
if x[i]<y[j]:#如果后插入比先插入要小,则互换
temp = x[i]
x[i] = y[j]
y[j] = temp
if x[i] % y[j] != 0: #如果x中元素对y中元素取余不为0
if j == len(y) - 1: #判断当前元素是否是y[]最后一个元素,即x[i]是否被y[j]全部元素取余
y.append(x[i])
continue
else: #如果找到有倍数关系的值,将大的值加入y[]中
if x[i] > y[j]:
y[j] = x[i]
break
处理方法如上,在这我简单的再说一下,
1.第一个插入y[]的元素不为1,因为1能被全部数整除
2.将含有倍数关系的较大值插入进来代替较小值
3.必须保证后进的值要大于当前比较元素
如对x[1,2,3,4,5]进行操作
首先取1,不符合条件,继续向下执行
取得2,此时y[]中为空,将2插入,继续执行
取得3,y[]不为空,取y[]长度为1,进行取余操作,3%2!=0,将3插入,继续执行
取得4,y[]不为空,取y[]长度为2,进行取余操作,4%2==0,判断4>2,将2替换为4,继续执行
取得5,5%4!=0,5%3!=0,插入
最终结果为[4,3,5]
最大公约数
对列表处理完成之后,我们开始进行最大公约数的处理
for i in range(len(y) - 1):
z.append(y[i])
z.append(y[i + 1])
while (z[i + 1] > 0):
l = z[0] % z[i + 1]
z[0] = z[i + 1]
z[i + 1] = l
首先取得y[]中前两位元素,将其插入新列表z
而后进行两位数的公约数算法
如果后一位数不为0,将第一位数%后一位数,取得的结果设为l,同时对数据进行交换,正如文章开头写的那行代码一样,直到后一位数为0,代表此时的两个数已经可以整除,此时的前一位数即为两数最大公因数
稍后我会解释为什么在这里要用z[0]来进行比较
而后我们进行公倍数的计算
最小公倍数
lcm = y[i] * y[i + 1] // z[0]
w.append(lcm)
if len(w) != 1:
get_lcm(w)
在这里已经能明显看到,z[0]是整个列表的最大公因数,因为每进行一次处理,z[]的后一位值就会变成0。
我们新建了一个w列表,用来存放所求得的最小公倍数,如果w的长度为1,说明里面只有一位数字,那就是我们要求的最小公倍数,如果不是,则递归调用,直到完成。
完整代码
def get_lcm(x):
y=[]
z=[]
w=[]
#列表处理
for i in range(len(x)):
if x[i] == 1:
continue
else:
if len(y) == 0:
y.append(x[i])
for j in range(len(y)):
if x[i]<y[j]:
temp = x[i]
x[i] = y[j]
y[j] = temp
if x[i] % y[j] != 0:
if j == len(y) - 1:
y.append(x[i])
continue
else:
if x[i] > y[j]:
y[j] = x[i]
break
#求公因数
for i in range(len(y) - 1):
z.append(y[i])
z.append(y[i + 1])
while (z[i + 1] > 0):
l = z[0] % z[i + 1]
z[0] = z[i + 1]
z[i + 1] = l
#求公倍数
l = y[i] * y[i + 1] // z[0]
w.append(l)
if len(w) != 1:
get_lcm(w) #继续递归执行
附上几个例子
1.x[1,2,3,4,5,2]
2.x[2,4,8,6]
3.x[15,25,30]
如果我有什么不对的地方,请大家帮我指正出来,我会再细致的考虑一下,谢谢大家。