【问题标题】:How to store recursive results while backtracking?回溯时如何存储递归结果?
【发布时间】:2018-05-03 04:28:56
【问题描述】:

我目前正在学习通过递归生成置换。

我发现以下代码非常适合打印排列,但我似乎无法存储值:堆栈中的所有值在升级时都会丢失。

def permute_util(str, count, result, level):

    if level == len(result):
        print(result)
        return

    for i in range(len(str)):
        if count[i] == 0:
            continue;
        result[level] = str[i]
        count[i] -= 1
        permute_util(str, count, result, level + 1)
        count[i] += 1

permute_util(list("ABC"), [2,1,1], [None]*len("AABC"), 0)

结果:

['A', 'A', 'B', 'C']
['A', 'A', 'C', 'B']
['A', 'B', 'A', 'C']
['A', 'B', 'C', 'A']
['A', 'C', 'A', 'B']
['A', 'C', 'B', 'A']
['B', 'A', 'A', 'C']
['B', 'A', 'C', 'A']
['B', 'C', 'A', 'A']
['C', 'A', 'A', 'B']
['C', 'A', 'B', 'A']
['C', 'B', 'A', 'A']

我已经尝试在基本情况下将结果添加到全局列表,但只有最新级别会被存储,而所有其他以前的值都会被覆盖,就像这样

 def permute_util(str, count, result, level):
    global glob 
    if level == len(result):
        **glob += [result]**
        return

    for i in range(len(str)):
        if count[i] == 0:
            continue;
        result[level] = str[i]
        count[i] -= 1
        permute_util(str, count, result, level + 1)
        count[i] += 1

permute_util(list("ABC"), [2,1,1], [None]*len("AABC"), 0)

['C', 'B', 'A', 'A']
['C', 'B', 'A', 'A']
['C', 'B', 'A', 'A']
['C', 'B', 'A', 'A']
['C', 'B', 'A', 'A']
['C', 'B', 'A', 'A']
['C', 'B', 'A', 'A']
['C', 'B', 'A', 'A']
['C', 'B', 'A', 'A']
['C', 'B', 'A', 'A']
['C', 'B', 'A', 'A']
['C', 'B', 'A', 'A']
['C', 'B', 'A', 'A']

也试过这个效果一样:

 def permute_util(str, count, result, level, lists):
    global glob 
    if level == len(result):
        return [result]


    for i in range(len(str)):
        if count[i] == 0:
            continue;
        result[level] = str[i]
        count[i] -= 1
        foo = permute_util(str, count, result, level + 1, lists)
        lists = lists + foo
        count[i] += 1

   lists = []
   permute_util(list("ABC"), [2,1,1], [None]*len("AABC"), 0, lists)

将基本案例中的所有“结果”存储在列表中并在完成时返回它的最佳方法是什么?

【问题讨论】:

  • 向我们展示您如何尝试将结果添加到全局列表中。很可能您做错了什么,但已经接近正常了,我们可以向您展示如何修复它 - 但如果我们看不到它,没有人可以为您修复它。
  • 同时,甚至比全局更好:要么传递另一个 results 列表(以 [] 开头,但你重复 results.append(result)),或者 return 结果而不是仅仅printing 它并在备份的路上收集它们。
  • 我试过了。追加也不起作用,当堆栈弹出时,先前的追加会被覆盖
  • 好吧,如果有任何帮助,我发现的一种解决方法是使用glob.append(''.join(result))
  • 谢谢,问题似乎是只附加了指向对象的指针,而不是实际值本身

标签: python recursion backtracking


【解决方案1】:

随着递归的进行,您会一遍又一遍地改变结果。
你可以这样做:

def permute_util(string, count, result, level):

    if level == len(result):
        print(result)
        res.append(tuple(result))   # stores current result as a copy in an immutable tuple
        return

    for i in range(len(string)):
        if count[i] == 0:
            continue;
        result[level] = string[i]
        count[i] -= 1
        permute_util(string, count, result, level + 1)
        count[i] += 1


if __name__ == '__main__':

    res = []

    permute_util(list("ABC"), [2, 1, 1], [None]*len("AABC"), 0)
    print(res)

【讨论】:

    【解决方案2】:

    Python 将指针附加到列表而不是实际列表。因此,您所拥有的是大量指向结果最终状态的指针,因此存在重复值。尝试在每次追加时创建副本,如下所示:

    final_ans = []
    def permute_util(str, count, result, level):
    
        if level == len(result):
            final_ans.append(result[:])    # if you don't explicitly want list, try final_ans.append(''.join(result))
            return
    
        for i in range(len(str)):
            if count[i] == 0:
                continue;
            result[level] = str[i]
            count[i] -= 1
            permute_util(str, count, result, level + 1)
            count[i] += 1
    
    permute_util(list("ABC"), [2,1,1], [None]*len("AABC"), 0)
    for ans in final_ans:
        print(ans)
    

    【讨论】:

    • 谢谢,这成功了!我根本没想到会有类似指针的行为
    猜你喜欢
    • 1970-01-01
    • 2018-08-17
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多