优化python3n+;1编程挑战

优化python3n+;1编程挑战,python,optimization,Python,Optimization,我正试图找到一个有效的解决方案,为3n+1的问题。我的代码使用了使用字典的备忘录。有人能提出一个或多个改进建议来帮助提高代码的执行时间吗?目前,当我提交代码时,我收到一个“超过时间限制”错误。如果有人对这个问题有有效的解决方案,请与我分享。请不要把这篇文章标为重复。我已经在stackoverflow上看到了post和其他人,但他们没有回答这里发布的问题。我的代码如下: import sys def recCycleLength(n,cycLenDict): if n==1:

我正试图找到一个有效的解决方案,为3n+1的问题。我的代码使用了使用字典的备忘录。有人能提出一个或多个改进建议来帮助提高代码的执行时间吗?目前,当我提交代码时,我收到一个“超过时间限制”错误。如果有人对这个问题有有效的解决方案,请与我分享。请不要把这篇文章标为重复。我已经在stackoverflow上看到了post和其他人,但他们没有回答这里发布的问题。我的代码如下:

import sys

def recCycleLength(n,cycLenDict):
    if n==1:
        return 1
    if n not in cycLenDict:
        if n%2==0:
            cycLen = recCycleLength(n//2, cycLenDict)
            cycLenDict[n] = cycLen + 1
            return cycLen+1
        else:
            cycLen = recCycleLength(3*n+1, cycLenDict)
            cycLenDict[n] = cycLen + 1
            return cycLen+1
    else:
        return cycLenDict[n]


def maxCycle(a, b):
    i = a
    mydict = {} 
    maxLength = 1
    while i <= b:
        m = recCycleLength(i, mydict)
        if m > maxLength:
            maxLength = m
        i = i + 1
    return maxLength


for line in sys.stdin:
    curr_line=line.split()
    num1 = int(curr_line[0])
    num2 = int(curr_line[1])
    if num1>num2:
        num1, num2 = num2, num1
    m = maxCycle(num1, num2)
    print("{} {} {}".format(num1, num2, m))
导入系统 def循环长度(n,循环长度): 如果n==1: 返回1 如果n不在cycLenDict中: 如果n%2==0: 循环长度=循环长度(n//2,循环长度) cycLenDict[n]=cycLen+1 返回周期+1 其他: 循环长度=循环长度(3*n+1,循环长度) cycLenDict[n]=cycLen+1 返回周期+1 其他: 返回周期[n] def最大循环(a、b): i=a mydict={} maxLength=1 而我最大长度: 最大长度=m i=i+1 返回最大长度 对于sys.stdin中的行: curr_line=line.split() num1=int(当前行[0]) num2=int(当前行[1]) 如果num1>num2: num1,num2=num2,num1 m=最大循环(num1,num2) 打印(“{{}{}”。格式(num1,num2,m))
我在您的代码中发现了问题。实际上,您并没有将上一个间隔中生成的
cycLenDict
保存到下一个间隔中。这就是为什么你的代码如此“慢”,因为它会一次又一次地生成所有可能的结尾。只需在全局范围内移动它或制作如下内容:

import sys


def rec(n, cache):
    if n in cache:
        return cache[n]
    if n % 2 == 0:
        cycle = rec(n//2, cache)
    else:
        cycle = rec(3*n+1, cache)
    cache[n] = cycle + 1
    return cache[n]


def cycle(a, b, cache):
    return max(rec(i, cache) for i in range(a, b+1))


if __name__ == '__main__':
    cache = {1: 1}
    for line in sys.stdin:
        a, b = map(int, line.split())
        a, b = min(a, b), max(a, b)
        m = cycle(a, b, cache)
        print("{} {} {}".format(a, b, m))

通过将所有计算结果缓存在
mydict
中,代码似乎正确地以最佳方式执行
maxCycle

但是,应用程序的输入由许多对要处理的值组成,
maxCycle
将重置
mydict={}
并从头开始计算所有内容

我建议大家记住这些结果。对原始代码的简单修改如下:

cycLenDict = {}   # global dictionary

def recCycleLength(n):   # no cycLenDict argument
    if n==1:
        return 1
    if n not in cycLenDict:
        # ...

def maxCycle(a, b):
    # ...

    while i <= b:
        m = recCycleLength(i)   # no myDict argument
导入系统 def循环(当前,计数=1): 如果当前==1: 返回计数 如果当前%2==0: 返回周期(当前/2,计数+1) 返回周期(当前*3+1,计数+1) def最大_循环(下部、上部): 最大值=0 对于范围内的电流(下限、上限): 结果=循环(电流,1) 如果结果>最大值: 最大值=结果 返回最大值 def总管(i、j): 如果i>j: (i,j)=(j,i) 打印(i,j,最大周期(i,j)) 如果名称=“\uuuuu main\uuuuuuuu”: 如果len(sys.argv)<3: 打印“用法:python文件名argv1 argv2” 打印“退出” 出口(0) main(int(sys.argv[1]),int(sys.argv[2]))
如果您有有效的解决方案,请改用。这可以讨论:OP不想提高可读性,而是提高速度。如果您提交了,请在问题中提供输入。我尝试在页面中输入示例,速度非常快。所以我错过了一些东西。uvaonlinejudge不向用户提供运行提交的代码的测试用例。示例输入只是为了用户可以在提交之前测试他们的代码是否有错误。。
def memoize(func):
    """decorate any function which takes positional arguments to cache its results"""

    func.results = {}  # results are stored globally as the funtion's attribute

    def memoized(*a):        # memoized version of func
        if a not in func.results:       # if not cached
            func.results[a] = func(*a)  # save to cache
        return func.results[a]          # return from cache
    return memoized


@memoize       # with this, recCycleLength is called only once for every n value
def recCycleLength(n):
    if n==1:
        return 1
    elif n%2==0:
        return recCycleLength(n//2) + 1
    else:
        return recCycleLength(3*n+1) + 1


def maxCycle(a, b):
    return max(recCycleLength(i) for i in range(a, b+1))
import sys
def cycle(current, count=1):
if current == 1:
    return count
if current % 2 == 0:
    return cycle(current / 2, count + 1)
return cycle(current * 3 + 1, count + 1)

def max_cycles(lower, upper):
    max = 0
    for current in range(lower, upper):
        result = cycle(current, 1)
        if result > max:
            max = result
    return max


def main(i, j):
    if i > j:
        (i, j) = (j, i)
    print (i, j, max_cycles(i, j))


if __name__ == "__main__":
    if len(sys.argv) < 3:   
        print 'usage: python filename argv1 argv2'
        print 'exiting'
        exit(0)
    main(int(sys.argv[1]), int(sys.argv[2]))