为了账号安全,请及时绑定邮箱和手机立即绑定

python中的递归没有达到正确的结果

python中的递归没有达到正确的结果

动漫人物 2021-11-16 17:00:28
我有一个问题,想要找到列表子集的总和为特定值的方式数。但是,如果我手动运行递归公式,我会得到一个与 python 代码不同的(正确的)值。我错过了什么,或者为什么我得到不同的结果?假设我有一个列表b = [2,3,2,1,4],目标值为T = 5. 然后将有 4 个子集与目标值相加:{b[0], b[1]}{b[0], b[2], b[3]}{b[4], b[3]}{b[1], b[2]}以下代码给出的结果为 2,但我希望它返回 4。b = [2,3,2,1,4]def subset_sum(T, idx):    if T < 0 or idx< 0:        return 0    if T == 0:        return 1    else:        return subset_sum(T, idx-1) + subset_sum(T-b[idx], idx-1) if __name__ == "__main__":    print(subset_sum(5, 4))基于@TomDalton 评论进行编辑:我尝试了这个并认为这可能是因为两个 if 语句没有同时检查 - 因此在 idx = 0 并且我们从值 T 中减去 b[0] 的情况下,然后在下一次迭代中它将返回 0,因为它在检查 T == 0 之前检查 idx < 0。虽然我不确定我的猜测的有效性
查看完整描述

3 回答

?
慕工程0101907

TA贡献1887条经验 获得超5个赞

这是带有额外检测的代码,可帮助跟踪输出,缩进递归调用。


您会注意到计数的一个严重问题:当您获得所需的总数并到达列表末尾时,您返回0而不是1。这会阻止您通过使用最终列表元素正确累积获得正确总数的解决方案,因为在检查是否获得正确总数之前,您会重复超过列表末尾。维修在底部。


indent = ""

b = [2,3,2,1,4]


def subset_sum(total, idx):

    global indent

    print(indent + "ENTER", total, idx)

    indent += "  "


    if total < 0 or idx < 0:

        result = 0

    elif total == 0:

        result = 1

    else:

        result = subset_sum(total, idx-1) + subset_sum(total-b[idx], idx-1) 


    indent = indent[2:]

    print(indent + "LEAVE", total, idx, result)

    return result


if __name__ == "__main__":

    print(subset_sum(5, 4))

输出:


ENTER 5 4

  ENTER 5 3

    ENTER 5 2

      ENTER 5 1

        ENTER 5 0

          ENTER 5 -1

          LEAVE 5 -1 0

          ENTER 3 -1

          LEAVE 3 -1 0

        LEAVE 5 0 0

        ENTER 2 0

          ENTER 2 -1

          LEAVE 2 -1 0

          ENTER 0 -1

          LEAVE 0 -1 0

        LEAVE 2 0 0

      LEAVE 5 1 0

      ENTER 3 1

        ENTER 3 0

          ENTER 3 -1

          LEAVE 3 -1 0

          ENTER 1 -1

          LEAVE 1 -1 0

        LEAVE 3 0 0

        ENTER 0 0

        LEAVE 0 0 1

      LEAVE 3 1 1

    LEAVE 5 2 1

    ENTER 4 2

      ENTER 4 1

        ENTER 4 0

          ENTER 4 -1

          LEAVE 4 -1 0

          ENTER 2 -1

          LEAVE 2 -1 0

        LEAVE 4 0 0

        ENTER 1 0

          ENTER 1 -1

          LEAVE 1 -1 0

          ENTER -1 -1

          LEAVE -1 -1 0

        LEAVE 1 0 0

      LEAVE 4 1 0

      ENTER 2 1

        ENTER 2 0

          ENTER 2 -1

          LEAVE 2 -1 0

          ENTER 0 -1

          LEAVE 0 -1 0

        LEAVE 2 0 0

        ENTER -1 0

        LEAVE -1 0 0

      LEAVE 2 1 0

    LEAVE 4 2 0

  LEAVE 5 3 1

  ENTER 1 3

    ENTER 1 2

      ENTER 1 1

        ENTER 1 0

          ENTER 1 -1

          LEAVE 1 -1 0

          ENTER -1 -1

          LEAVE -1 -1 0

        LEAVE 1 0 0

        ENTER -2 0

        LEAVE -2 0 0

      LEAVE 1 1 0

      ENTER -1 1

      LEAVE -1 1 0

    LEAVE 1 2 0

    ENTER 0 2

    LEAVE 0 2 1

  LEAVE 1 3 1

LEAVE 5 4 2

2

修理


在检查是否超出列表末尾之前,只需检查是否成功:


if total == 0:

    result = 1

elif total < 0 or idx < 0:

    result = 0


查看完整回答
反对 回复 2021-11-16
?
墨色风雨

TA贡献1853条经验 获得超6个赞

您是否考虑过迭代方法?itertools.combinations想到


itertools.combinations(iterable, r)

从输入可迭代返回 r 个长度的元素子序列。


组合按字典排序顺序发出。因此,如果输入可迭代对象已排序,则组合元组将按排序顺序生成。


有了这个,您可以执行以下操作:


from itertools import combinations


def count_subsets(main_list, target):

    result = 0

    for i in range(len(main_list)):

        sets = combinations(main_list, i)

        result += sum(sum(subset) == target for subset in sets)

    return result


查看完整回答
反对 回复 2021-11-16
?
慕哥6287543

TA贡献1831条经验 获得超10个赞

问题是你在 idx < 0 时退出,但没有先检查是否 T == 0(这将是一个解决方案)。您应该首先测试 T == 0:


if T == 0:

    return 1

elif T < 0 or idx< 0:

    return 0

else:

    return subset_sum(T, idx-1) + subset_sum(T-b[idx], idx-1) 


查看完整回答
反对 回复 2021-11-16
  • 3 回答
  • 0 关注
  • 203 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信