鱼C论坛

 找回密码
 立即注册
查看: 12030|回复: 41

题目14:找出以100万以下的数字开始的最长序列

[复制链接]
发表于 2018-4-4 10:20:44 | 显示全部楼层
  1. import time


  2. start = time.time()
  3. cntlist = []
  4. for i in range(2, 1000000):
  5.     numlist = [i]
  6.     num = i
  7.     while num != 1:
  8.         if num % 2 == 0:
  9.             num /= 2
  10.         else:
  11.             num = num * 3 + 1
  12.         numlist.append(num)
  13.         if num in numlist:

  14.     cntlist.append(len(numlist))
  15. print max(cntlist)
  16. print time.time() - start
复制代码


十分初级的版本。考虑优化点有2:

1、类似素数筛选法:已经算过的数的2的n次方倍数的数,计数直接+n,结束。
2、维护一个数的序列的表,如果出现某个数在列表内,则计数直接加上列表后面的长度,结束。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-4-4 12:43:27 | 显示全部楼层
  1. (837799, 524)
  2. 2.58100008965
复制代码


优化了一下,速度提高了不少。不过最后的字典里取结果可能慢了。还有优化的空间。代码如下:
  1. import time


  2. def longestCollatz(n=1000001):
  3.     start = time.time()
  4.     collatzdict = {}  #维护一个统一的collatz的统计字典,初始为[2:2]
  5.     numlist = [True] * (n - 1) #默认所有数都未被‘挖掉’, 从2 开始
  6.     for i in range(2, n):
  7.         count = 0
  8.         num = i
  9.         if numlist[i - 2] == True: #若一个数未被挖掉,计算数量
  10.             while num != 1:
  11.                 num = num * 3 + 1 if num % 2 else num / 2
  12.                 count += 1
  13.                 if num in collatzdict: #若计算到某个步骤,产生了已经出现过的数,则直接加上该数的计数,计数结束
  14.                     count += collatzdict[num]
  15.                     break
  16.             collatzdict[i] = count
  17.             numlist[i - 2] = False
  18.             if i < n / 2:             #以i为基数,挖掉i的2的j次方倍的所有的数
  19.                 j = 1
  20.                 while i * pow(2, j) < n:
  21.                     if numlist[i] == True:
  22.                         numlist[i * pow(2, j) - 2] = False #挖掉第i个数2的j次方倍的数
  23.                         collatzdict[i * pow(2, j)] = collatzdict[i] + j
  24.                     j += 1
  25.     print list(sorted(collatzdict.items(), key=lambda x:x[1], reverse=True))[0]
  26.     print time.time() - start


  27. if __name__ == '__main__':
  28.     longestCollatz()
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-4-4 12:57:11 | 显示全部楼层
阿bang 发表于 2018-4-4 12:43
优化了一下,速度提高了不少。不过最后的字典里取结果可能慢了。还有优化的空间。代码如下:
  1. import time


  2. def longestCollatz(n=1000001):
  3.     start = time.time()
  4.     collatzdict = {}  #维护一个统一的collatz的统计字典,初始为[2:2]
  5.     numlist = [True] * (n - 1) #默认所有数都未被‘挖掉’, 从2 开始
  6.     maxnum = 2
  7.     maxcnt = 2
  8.     for i in range(2, n):
  9.         count = 0
  10.         num = i
  11.         if numlist[i - 2] == True: #若一个数未被挖掉,计算数量
  12.             while num != 1:
  13.                 num = num * 3 + 1 if num % 2 else num / 2
  14.                 count += 1
  15.                 if num in collatzdict: #若计算到某个步骤,产生了已经出现过的数,则直接加上该数的计数,计数结束
  16.                     count += collatzdict[num]
  17.                     break
  18.             collatzdict[i] = count
  19.             if count > maxcnt:
  20.                 maxcnt = count
  21.                 maxnum = i
  22.             numlist[i - 2] = False
  23.             if i < n / 2:             #以i为基数,挖掉i的2的j次方倍的所有的数
  24.                 j = 1
  25.                 while i * pow(2, j) < n:
  26.                     if numlist[i] == True:
  27.                         numlist[i * pow(2, j) - 2] = False #挖掉第i个数2的j次方倍的数
  28.                         collatzdict[i * pow(2, j)] = collatzdict[i] + j
  29.                         if collatzdict[i * pow(2, j)] > maxcnt:
  30.                             maxcnt = collatzdict[i * pow(2, j)]
  31.                             maxnum = i * pow(2, j)
  32.                     j += 1


  33.     # print list(sorted(collatzdict.items(), key=lambda x:x[1], reverse=True))[0]
  34.     print maxnum, maxcnt
  35.     print time.time() - start


  36. if __name__ == '__main__':
  37.     longestCollatz()
复制代码


再改了一下,只需要找最大的,不需要最后排序字典的话,会快一点

  1. 837799 524
  2. 1.69199991226
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-10-24 03:28

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表