求多个数的最小公倍数和最大公因数

做练习的时候碰到了这种问题,对于两个数的求法我们可以用辗转相除法

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]

在这里插入图片描述
如果我有什么不对的地方,请大家帮我指正出来,我会再细致的考虑一下,谢谢大家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值