如何在Python的min/max函数中使用条件语句?动态规划代码报错排查
问题分析与解决
首先,你的代码出现错误的核心原因不是min函数里的条件表达式写法,而是用了x/3这种浮点数除法——递归调用f(x/3)时传入的是浮点数参数,而列表dpt的索引只能是整数,这会直接触发TypeError: list indices must be integers or slices, not float。
第一步:修复直接错误+修正初始化问题
先把浮点数除法换成整数除法//,保证传入的参数是整数。另外你的初始化有个小坑:dpt数组初始全为0,但dpt[1]本身就是0,其他未计算的位置(比如dpt[3])会被误判为已计算完成,返回错误结果。建议用None标记未计算的状态。
修正后的递归版本代码:
# 用None标记未计算的状态,避免初始0值干扰判断 dpt = [None] * (10**6 + 1) dpt[1] = 0 def f(x): if dpt[x] is not None: return dpt[x] # 先初始化候选值为"x-1"的步数+1(每一步操作都要算一次) res = f(x-1) + 1 # 能被3整除时,对比"x//3"的步数+1 if x % 3 == 0: res = min(res, f(x//3) + 1) # 能被2整除时,对比"x//2"的步数+1 if x % 2 == 0: res = min(res, f(x//2) + 1) dpt[x] = res return res N = int(input()) print(f(N))
这里还要提醒你:之前的代码漏掉了加1——不管是除以3、除以2还是减1,都是一步操作,必须在子问题的结果上加1才是当前问题的正确步数!
更适合大规模数据的迭代版本
当N接近1e6时,递归会触发栈溢出(Python默认递归深度只有约1000),所以更稳妥的方式是用迭代式动态规划,效率也更高:
N = int(input()) dpt = [0] * (N + 1) for x in range(2, N+1): # 先取"x-1"的步数+1 dpt[x] = dpt[x-1] + 1 # 能被2整除时取更小值 if x % 2 == 0: dpt[x] = min(dpt[x], dpt[x//2] + 1) # 能被3整除时取更小值 if x % 3 == 0: dpt[x] = min(dpt[x], dpt[x//3] + 1) print(dpt[N])
关于min/max中使用条件表达式的正确姿势
回到你最初的疑问:在min/max里用条件表达式是可行的,但要注意这几点:
- 条件表达式的两个分支返回值类型要一致(比如你之前用9999当“无效值”是可以的,但要保证和有效分支的返回值类型相同)
- 尽量避免魔法值(比如9999),拆分到单独的if判断里代码可读性更好
- 复杂条件下,先初始化基础值再逐步对比,比把所有逻辑塞在min函数里更易维护
内容的提问来源于stack exchange,提问作者windowcow




