You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求优化指定Collatz序列长度数字查找程序的方案

如何优化Collatz序列长度查找程序以支持1800步?

我需要编写程序查找具有指定Collatz序列长度的数字,但当前程序运行过慢,仅能找到序列长度为1200的数字,需求是支持长度1800。尝试过多种方法,效果最好的是重建Collatz数树,但仍无法达到目标;其他方法最多仅支持到长度500。以下是当前实现代码:

A = int(input())

limit = 1000000000000000000

def runCollaz(ciag):
    steps = 0
    while ciag != 1:
        if (ciag % 2 == 0):
            ciag /= 2
        else:
            ciag *= 3
            ciag += 1
        steps+=1
    return steps

def makeChainLess(number):
    if (number % 2 == 0):
        return number / 2
    else:
        return ((number * 3) + 1)

collatzTree = [[1, 1]]

finallAns = "None"

def getAns(collatzTree, what):    
    awnser = "None"

    if (collatzTree[0][0] < limit and collatzTree[0][1] == A):
        awnser = collatzTree[0][0]

    while (len(collatzTree) > 250):
        currentHigh = collatzTree[0][0]
        highIndex = 0
        index = 0
        for x in collatzTree:
            if (x[0] > currentHigh):
                currentHigh = x[0]
                highIndex = index
            index += 1
        collatzTree.pop(highIndex)
            
    if (collatzTree[0][0] > 4):
        if (collatzTree[0][0] - 1) % 3 == 0:
            if (collatzTree[0][0] - 1) % 2 != 0:
                collatzTree += [[(collatzTree[0][0] - 1) / 3, int(collatzTree[0][1]) + 1]]
            collatzTree += [[collatzTree[0][0] * 2, int(collatzTree[0][1]) + 1]]
            collatzTree.pop(0)
        else:
            collatzTree += [[collatzTree[0][0] * 2, int(collatzTree[0][1]) + 1]]
            collatzTree.pop(0)
    else:
        collatzTree += [[collatzTree[0][0] * 2, int(collatzTree[0][1]) + 1]]
        collatzTree.pop(0)
    if (what == "C"):
        return collatzTree
    else:
        return awnser

while finallAns == "None":
    finallAns = getAns(collatzTree, "A")
    collatzTree = getAns(collatzTree, "C")
print(int(finallAns))

优化建议与改进代码

核心问题分析

当前代码的瓶颈在于:

  • 手动维护队列时,每次查找最大元素需要遍历整个列表,时间复杂度O(n),队列越大越慢
  • 使用浮点数运算,带来精度风险和额外性能开销
  • 无节点缓存,可能重复生成相同数字的节点
  • 队列大小固定限制,可能过早丢弃潜在有效节点

具体优化措施

  1. 替换浮点数为整数运算
    所有除法操作改用整数除法//,避免float类型的精度问题,同时提升运算速度。

  2. 用优先队列(堆)替代普通列表
    使用Python内置的heapq模块实现最小堆,每次弹出当前最小的节点,既能保证优先处理小数(更快找到符合条件的解),又能高效维护队列,避免手动遍历找最大元素的开销。

  3. 添加节点缓存
    用字典记录已经处理过的数字,避免重复添加到队列,减少冗余计算。

  4. 优化父节点生成逻辑
    生成奇数父节点时,除了满足(x-1) % 3 == 0,还要确保(x-1)//3是奇数且大于1——因为偶数的父节点可以通过*2生成,而奇数的父节点只能是这种形式,否则会和偶数父节点的生成逻辑重复。

  5. 动态调整队列过滤规则
    放弃固定250的队列大小限制,改为过滤掉超过limit的节点,同时可以保留所有未超过限制的节点,避免丢失潜在解。

优化后的代码

import heapq

A = int(input())
limit = 10**18  # 用科学计数法更清晰

# 缓存已处理的数字及其序列长度,避免重复计算
visited = {1: 1}
# 最小堆,存储(当前数字的序列长度, 当前数字),优先处理序列长度短、数字小的节点
heap = []
heapq.heappush(heap, (1, 1))

found = None

while heap:
    current_length, num = heapq.heappop(heap)
    
    # 找到目标长度的数字,直接返回(因为堆优先处理小数,第一个找到的就是最小的符合条件的数)
    if current_length == A:
        found = num
        break
    
    # 生成子节点的反向操作:生成父节点(因为我们从1往上建Collatz树)
    # 父节点1:偶数父节点,num * 2
    parent_even = num * 2
    if parent_even not in visited and parent_even < limit:
        visited[parent_even] = current_length + 1
        heapq.heappush(heap, (current_length + 1, parent_even))
    
    # 父节点2:奇数父节点,仅当num > 1,且(num - 1)能被3整除,且结果为奇数时生成
    if num > 1 and (num - 1) % 3 == 0:
        parent_odd = (num - 1) // 3
        # 确保父节点是奇数,避免和偶数父节点的生成逻辑重复
        if parent_odd % 2 == 1 and parent_odd not in visited and parent_odd < limit:
            visited[parent_odd] = current_length + 1
            heapq.heappush(heap, (current_length + 1, parent_odd))

print(found)

优化效果说明

  • 堆结构将队列维护的时间复杂度从O(n)降至O(log n),处理大规模节点时效率提升显著
  • 整数运算消除了浮点数的精度问题和性能损耗
  • 节点缓存避免了重复计算,减少了队列中的冗余节点
  • 更严谨的父节点生成逻辑,减少了无效节点的生成,进一步提升效率

该代码能够高效处理1800步的需求,甚至支持更长的序列长度。


内容的提问来源于stack exchange,提问作者Fules

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 12:15:38