题目:
求0-9所有数字组成的k位不重复的数字。
说明:我们要找到所有不重复数字的`k`位组合。这个问题相对于前一个问题(搜索与回溯算法②)增加了一个约束:每个数字只能使用一次。这就需要在代码中加入剪枝逻辑来确保不违反这个约束。
Python实现过程:
def backtrack(start, path, k, n, used, results):"""回溯算法的辅助函数。:param start: 下一个添加的数字的起始位置:param path: 当前构建的路径,代表一个组合:param k: 组合中所需的数字个数:param n: 可选数字的最大值:param used: 标记数字是否已被使用的布尔数组:param results: 存储所有有效组合的列表"""# 如果路径长度等于k,说明找到了一个有效的k位数,将其加入结果列表if len(path) == k:results.append("".join(map(str, path)))returnfor i in range(start, n + 1):# 剪枝条件:如果数字i已经在路径中使用过,则跳过if used[i]:continue# 添加当前数字到路径,并标记为已使用path.append(i)used[i] = True# 继续递归填充下一个数字,注意数字不可重复使用,所以起始位置是i+1backtrack(i + 1, path, k, n, used, results)# 回溯:撤销之前的选择,移除路径中的最后一个数字,并标记为未使用used[i] = Falsepath.pop()def generate_combinations(k, n=9):"""生成所有可能的k位数的组合,其中每个数字只能使用一次。:param k: 组合中所需的数字个数:param n: 可选数字的最大值,默认为9:return: 包含所有k位数的列表"""results = [] # 存储所有组合的结果列表used = [False] * (n + 1) # 初始化数字使用标记数组,所有数字都标记为未使用backtrack(1, [], k, n, used, results) # 从数字1开始进行回溯return results# 示例:生成所有3位数的组合,其中每个数字只能使用一次
k_digit_combinations = generate_combinations(3)
for combination in k_digit_combinations:print(combination)
分析:
在这个例子中:
回溯过程
体现在函数`backtrack`中,当我们递归调用`backtrack`函数探索所有可能的组合,然后通过`path.pop()`和`used[i] = False`来撤销当前的选择,这样就可以回到前一个状态,尝试其他可能的数字。path.pop()是实际移除值,used[i] = False是将移除的该值状态进行回退。
剪枝过程
体现在检查`used[i]`的条件中。如果`used[i]`为`True`,表示当前数字`i`已经在当前的组合`path`中使用过,就跳过这个选择,这样就避免了生成重复数字的组合。
通过这样的剪枝策略,显著减少了搜索空间,因为不再考虑那些违反约束条件的路径。这使得算法更有效率,特别是在组合数非常多的情况下。
准确来说这样的搜索与回溯实际上是对枚举算法的一种较好的优化,若剪枝得当是可以考虑选用的,相对枚举来说不容易溢出。