如何调整代码使用回溯算法来解决组合问题

时间:2017-10-13 08:22:34

标签: python algorithm backtracking

问题描述:

返回数组的所有组合。例如,有一个数组[1,2,3],其结果是:

[]
[1]  [2]  [3]
[1, 2]  [1, 3]  [2, 3]
[1, 2, 3]

是的,我知道有很多方法可以解决这个问题。但我试图用回溯算法解决它。下面是我的代码:

def p(arr):
    ret = []
    #using visited boolean array to avoid duplicate traverse and backtracking.
    visited = [False] * len(arr)
    def dfs(start_idx, temp)
        ret.append(temp)
        for i in range(start_idx, len(arr)):
            if not visited[i]:
                visited[i] = True
                dfs(start_idx + 1, temp + [arr[i]])
                visited[i] = False
    dfs(0, [])
    return ret 

返回[[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3], [3, 2]],答案错误[3, 2]

根据我的理解,dfs +回溯应该只在一个从左到右的方向上遍历数组。但显然[3,2]是相反的方向。

如何理解这一点以及如何使用我的代码修复此问题?

1 个答案:

答案 0 :(得分:3)

您的算法使用布尔列表来跟踪选择的元素。但这不是一个好方法:一旦你选择了一个元素 i ,你应该确保你只能选择索引 j>的元素。我

您似乎使用start_idx执行此操作,但实际上在递归调用中您*仅增加start_idx

因此,快速解决方法是将start_index设置为i+1

def p(arr):
    ret = []
    #using visited boolean array to avoid duplicate traverse and backtracking.
    visited = [False] * len(arr)
    def dfs(start_idx, temp):
        ret.append(temp)
        for i in range(start_idx, len(arr)):
            if not visited[i]:
                visited[i] = True
                dfs(i + 1, temp + [arr[i]])  # i instead of start_idx
                visited[i] = False
    dfs(0, [])
    return ret

现在这会导致visited过时,所以我们可以删除这些检查:

def p(arr):
    ret = []
    def dfs(start_idx, temp):
        ret.append(temp)
        for i in range(start_idx, len(arr)):
            dfs(i + 1, temp + [arr[i]])
    dfs(0, [])
    return ret

话虽如此,我建议使用itertools.combinations