NO.1 尝试优化a+b+b=1000(abc为自然数),且a^2+b^2=c^2,如何求出a,b,c 的问题

第一条,枚举法,那就是用一个数一个数去试试,假设a=0,b=0,这时候c=1000,用循环一个一个的试
,贴一下这个笨拙的代码,为了验证运行消耗的时间引入了time模块

import time
start_time=time.time()
for a in range(1,1001):
    for b in range(1, 1001):
        for c in range(0, 1001):
            if a+b+c==1000 and a**2+b**2==c**2:
                print(a,b,c)
end_time=time.time()
print('time:%d'%(end_time-start_time))
print('结束')

运算结果如下:

200 375 425
375 200 425
time:150
结束


程序算完一共用了150秒,这个时候我的CPU占用率甚至到达了96%
那现在我们来试试当abc的范围扩大到10000时需要多少时间

import time
start_time=time.time()
for a in range(1,10001):
    for b in range(1, 10001):
        for c in range(1, 10001):
            if a+b+c==10000 and a**2+b**2==c**2:
                print(a,b,c)
end_time=time.time()
print('time:%d'%(end_time-start_time))
print('结束')

而这个10000的计算量在我运行超过1个小时后还未计算出结果我就放弃这种计算方式,这显然不是我想要的
这个方案解决这个问题是可以,但一旦这个范围过大,运算时间就会爆掉,所以我们需要更快时间并且更节省内存的方法
现在我做一个小小的优化,当a,b的循环语句后加入一个 c=1000-a-b 来替换掉原来的 for c in range(0, 1001) ,因为本身abc三者的范围关系是确定的,而这里我们我们不需要再多加一个c循环来计算c的值,再修改后运行速度就得到了明显的提升

import time
start_time=time.time()
for a in range(1,1001):
    for b in range(1, 1001):
        c=1000-a-b
        if a**2+b**2==c**2:
            print(a,b,c)
end_time=time.time()
print('time:%d'%(end_time-start_time))
print('结束')

运行结果如下:

200 375 425
375 200 425
time:1
结束


可以看到运行速度由原来的15秒提升到了1秒,而我们来看看范围扩大到10000的情况

import time
start_time=time.time()
for a in range(1,10001):
    for b in range(1, 10001):
        c=10000-a-b
        if a**2+b**2==c**2:
            print(a,b,c)
end_time=time.time()
print('time:%d'%(end_time-start_time))
print('结束')

运行结果如下:

2000 3750 4250
3750 2000 4250
time:177
结束


在引入第二次结果后我们可以看出一个问题,那就是解决同一个问题的方法有多种,第一次写的程序与第二次写的程序是有差别的,算法与算法之间有着效率的差别,然而即使是第二种方法在处理超过1W的范围后计算速度也十分缓慢,令人难以忍受,所以我尝试继续来优化
在第二次方法中:
c=10000-a-b
if a+b+c==1000 and a**2+b**2==c**2
这两段实际可以可以糅合在一段,我们不需要重新设立变量c,那么直接在判断语句中计算(1000-a-b)的值会怎么样呢?

for a in range(1,1001):
    for b in range(1,1001):
        if a**2+b**2==(1000-a-b)**2:
            print(a,b,1000-a-b)

这里计算出来的结果是

200 375 425
375 200 425
time:1
结束


咦,似乎看不出与上一段的计算时间的区别,那我们再试试把范围提升到10000

这里计算出来的结果是

2000 3750 4250
3750 2000 4250
time:154
结束


在这里可以看出来这一次的计算时间比上一次似乎有所提高,但这还是不能满足我期望思维快速计算的要求,再又经过思考后,现在我们回到题目,首先是两个条件:
1、a+b+c=1000
2、a^2+b^2=c^2
针对已知条件1,2,可通过a + b + c = 1000得出a^2+b^2+c^2+2ab+2ac+2bc=1000000,把a^2+b^2=c^2和c=1000-a-b代入后化简得出公式1000(a+b)-2ab=500000
然后用新的公式带入原来的脚本中

for a in range(1,1001):
    for b in range(1,1001):
        if 1000*(a+b) - 2*a*b == 500000:
            print(a,b,1000-a-b)

这里1000的计算时间还是看不出差异,我直接计算范围为10000的结果

这里计算出来的结果是

2000 3750 4250
3750 2000 4250
time:40
结束


现在可以看出这个算法较之前的工作时间提升了3分之2,但对于十万量的数据计算时间依然还是漫长,我觉得这个速度我依然不满意,而在读过算法图解后我明白了有一种很简单的算法叫2分法,然后我将这种方法尝试写入我的程序中
再次思考问题
a显然不等于b,如果a等于b,则c不能为整数,为了避免重复,比如a和b交换位置的情况,不妨考虑a < b < c,则可以知道a<1000/3, c>1000/3, b<1000/2;

import time
start_time=time.time()
a_range = 10000 // 3
b_range = 10000 // 2
for a in range(1, a_range):
    b_high =b_range
    b_low = a + 1
    while True:
        b = (b_low + b_high) // 2
        c = 10000 - a - b
        if a ** 2 + b ** 2 == c ** 2:
            print("a=%d, b=%d, c=%d" % (a, b, c))
            break
        elif a ** 2 + b ** 2 > c ** 2:
            b_high = b
        elif a ** 2 + b ** 2 < c ** 2:
            b_low = b + 1
        if b_low == b_high :
            break
end_time=time.time()
print('time:%d'%(end_time-start_time))
print('结束')

在这里,10000运行的时间还是0,而100000的运行结果如下:


a=20000, b=37500, c=42500
a=21875, b=36000, c=42125
time:2
结束

一百万范围的结果为:

a=200000, b=375000, c=425000
a=218750, b=360000, c=421250
time:26
结束

这次的结果为26秒,这个计算方式是我能想到最简洁的,希望有更多的朋友给我提供更多更好的思路和方法

猜你喜欢

转载自blog.csdn.net/weixin_43051776/article/details/82117949