You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在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

火山引擎 最新活动