最近看一个学习视频,里面讲了个Hailstone 雹石序列,描述如下:
感觉用Python很好实现:
#Hailstone序列
def haistone(n):
hai_list = []
while n > 1:
hai_list.append(n)
if n%2: #奇数
n = 3*n + 1
else: #偶数
n = n//2
else:
hai_list.append(1)
return hai_list
试下:
res = hailstone(42)
print(res)
#[42, 21, 64, 32, 16, 8, 4, 2, 1]
网上搜了下,有这么个思考题:显示哪个初始数字(小于50000)创建最长的冰雹序列?
最简单的办法是一个一个的试, 判断出每个数字冰雹序列的长度,然后取最大的即可。
def get_haistone_length(n):
i = 1
while n > 1:
if n%2:
n = 3*n + 1
i += 1
else:
n = n//2
i += 1
return i
def get_longest_num(a,b):
num = 1
key = 1
for i in range(a, b+1):
if get_haistone_length(i) > num:
num = get_haistone_length(i)
key = i
return (key, num)
试下结果:
b = get_longest_num(1,50000)
print(b)
#(35655, 324)
[Finished in 1.6s]
再试个更大的:
b = get_longest_num(1,500000)
print(b)
#(410011, 449)
[Finished in 16.7s]
花费时间已经很长了,在原有方法的基础上进行适当优化,比如说10000这个数字,第一步先除以2,得到5000,此时很显然,5000这个数字的冰雹序列长度我们之前算过了,所以直接直接可以得到10000的结果为5000的加上1。
算法如下:
def get_num(a,b):
dict1 = {}
max = 1
num = 1
for x in range(a, b+1):
i = 1
m = x
while x > 1:
if x in dict1:
i += dict1[x] - 1
break
else:
if x%2:
x = 3*x + 1
i += 1
else:
x = x//2
i += 1
dict1[m] = i
if i > max:
max = i
num = m
return (num, max)
试一下:
lis = get_num(1,500000)
print(lis)
#(410011, 449)
[Finished in 1.9s]
可以看出确实有很明显的速度提升。