第一条,枚举法,那就是用一个数一个数去试试,假设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秒,这个计算方式是我能想到最简洁的,希望有更多的朋友给我提供更多更好的思路和方法