今天遇到如下问题,大致意思是:
第二次:
出发点是尽量缩减之前代码遍历的区域,试着能不能计算出来
思路如下:
1、按顺序将满足条件的数存入列表result
2、新生成的数是由
1、之前的数乘以2或3或5
2、并且大于result[-1]
3、取其中的最小值
但丢进测试窗口后,仍返回超时异常。
第三次:
由于如果不能成功提交代码,不能参考其他网友的思路,革命只有靠自己了
静下心来一想,之前的思路全是对每个数进行循环遍历,当数不断增大时,计算量几何增长
能不能找到其中的部分规律以简化,由于远离数学问题一个世纪,此处略去一天的思考时间
最后的大致思路如下:
1、新的数(new)肯定为之前某个数(x) 乘以2或3或5 得到
2、如果 x 被使用后,之后的计算肯定是从x以后的数开始计算(所以重点是记录x的下标ind,每当计算x满足要求时,ind向后移动一位)
3、现在的问题是:可以 乘以2或3或5 ,那么需要三个参数记录对应的下标(ind2、ind3、ind5)
此处比较难以理解,尝试解释下:
1、新的数new是目前为止最大的数
2、当new只是2的倍数时,那么这个new如果在下一次调用时(在此时,这个数应该是上文中的x),只可能*2(因为乘以其他数肯定比乘以2大,不满足尽量小的条件)
3、当new是2/3的公倍数时,那么new如果在下一次调用时(在此时,这个数应该是上文中的x),首先只可能*2,但在下下次调用时,*3可能会满足要求
4、当new是2/3/5或者3/5的公倍数时,同理3
5、为了要记录x的index,所以每当new是2|3|5的倍数时,对应的ind应该自增1
不基于数学理论聊算法问题就是耍流氓, 大家看不明白的话直接看代码吧,可能明白点
欣喜若狂!!!
一个数需要满足 2**i * 3**j * 5**k ,求第5000个满足这条件的最小值
A Hamming number is a positive integer of the form 2i3j5k, for some non-negative integers i, j, and k.
Write a function that computes the nth smallest Hamming number.
Specifically:
The first smallest Hamming number is 1 = 203050
The second smallest Hamming number is 2 = 213050
The third smallest Hamming number is 3 = 203150
The fourth smallest Hamming number is 4 = 223050
The fifth smallest Hamming number is 5 = 203051
The 20 smallest Hamming numbers are given in example test fixture.
Your code should be able to compute all of the smallest 5,000 (Clojure: 2000) Hamming numbers without timing out.
乍一看不难啊,直接用两层循环开搞(外层循环记录次数,内层循环判断是否满足条件)
第一次脚本如下:
def hamming(n):
"""Returns the nth hamming number"""
num = 1
count = 0 #记录次数
while 1: #外层循环记录个数
num_temp = num
while 1: #内层循环判断条件
if num_temp%2 == 0:
num_temp /= 2
elif num_temp%3 == 0:
num_temp /= 3
elif num_temp%5 == 0:
num_temp /= 5
else:
break
if num_temp == 1:
count += 1
if count >= n:
return num
else:
num += 1
else:
num += 1
逻辑没问题,但计算第5000个数已经力不从心了,现在才反应过来这道题原来考的是算法
第二次:
出发点是尽量缩减之前代码遍历的区域,试着能不能计算出来
思路如下:
1、按顺序将满足条件的数存入列表result
2、新生成的数是由
1、之前的数乘以2或3或5
2、并且大于result[-1]
3、取其中的最小值
得到的
def hamming(n):
"""Returns the nth hamming number"""
result = [1]
for i in range(n-1):
a = int(len(result)/5)
add = [x*y for x in result[a:]
for y in [2,3,5] if x*y > result[-1]] #在此之前的每个数分别乘以2/3/5,并且大于result[-1]的最小值
result.append(min(add))
return result[-1]
现在计算第5000个数,已经能在10s左右计算出来
但丢进测试窗口后,仍返回超时异常。
第三次:
由于如果不能成功提交代码,不能参考其他网友的思路,革命只有靠自己了
静下心来一想,之前的思路全是对每个数进行循环遍历,当数不断增大时,计算量几何增长
能不能找到其中的部分规律以简化,由于远离数学问题一个世纪,此处略去一天的思考时间
最后的大致思路如下:
1、新的数(new)肯定为之前某个数(x) 乘以2或3或5 得到
2、如果 x 被使用后,之后的计算肯定是从x以后的数开始计算(所以重点是记录x的下标ind,每当计算x满足要求时,ind向后移动一位)
3、现在的问题是:可以 乘以2或3或5 ,那么需要三个参数记录对应的下标(ind2、ind3、ind5)
此处比较难以理解,尝试解释下:
1、新的数new是目前为止最大的数
2、当new只是2的倍数时,那么这个new如果在下一次调用时(在此时,这个数应该是上文中的x),只可能*2(因为乘以其他数肯定比乘以2大,不满足尽量小的条件)
3、当new是2/3的公倍数时,那么new如果在下一次调用时(在此时,这个数应该是上文中的x),首先只可能*2,但在下下次调用时,*3可能会满足要求
4、当new是2/3/5或者3/5的公倍数时,同理3
5、为了要记录x的index,所以每当new是2|3|5的倍数时,对应的ind应该自增1
不基于数学理论聊算法问题就是耍流氓, 大家看不明白的话直接看代码吧,可能明白点
(以后一定要学习数学了)
def hamming(n):
"""Returns the nth hamming number"""
result = [1]
ind2 = ind3 = ind5 = 0 #每当add为对应数的倍数时,index += 1
count = 1
while n>count:
add = min(result[ind2]*2, result[ind3]*3, result[ind5]*5)
if add == result[ind2]*2:
ind2 += 1
if add == result[ind3]*3:
ind3 += 1
if add == result[ind5]*5:
ind5 += 1
count += 1
result.append(add)
return result[-1]
此时,计算第5000个数【50837316566580】仅仅0.3s,顺利通过测试
欣喜若狂!!!