1.回溯算法很容易把自己绕晕,但是如果从for循环入手理解,容易达到事半功倍的效果.
2.给定题目:(从1-4中找出2位数的组合)
2.1案例一:我们做此类题的第一思路是用双层for循环,代码如下
def fun(n, k):
for i in range(1, n+1):
for j in range(i+1. n+1):
print(i, j)
res = fun(4, 2)
print(res)
# 输出结果为12,13,14,23,24,34
# 注意range(5,5)是不会输出任何东西的,所以每一层for循环的截止都是n+1
2.2案例二:那么从1-4中找到三位数的组合呢?,依然可以使用三层for循环解决
def fun(n, k):
for i in range(1,n+1)
for j in range(i,n+1):
for m in range(j,n+1):
print(i,j,m)
res = fun(4,3)
print(res)
# 输出结果
#123 124 134 234
2.3很显然如果我要你求100个数里面的其中某98个数的组合呢?
难道要写98个循环吗?显然是不可能的,因此我们引出了回溯算法求解此类问题.
3.题目转换
题目描述:给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
3.1根据以上的案例我们可以明显看出一些规律
# 案例一关键代码
for i in range(1, n+1):
for j in range(i+1. n+1):
print(i, j)
# 案例二关键代码
for i in range(1,n+1)
for j in range(i,n+1):
for m in range(j,n+1):
print(i,j,m)
# 比较得知:
# 内层循环的范围(m,n),其中m由上一层的循环遍历得出,n固定
# 因此我们可以想到把内层抽取成一个函数的思想,由此引出了递归和回溯
# 抽取后代码
res = [] # 存放最终结果
path = [] # 存放过程结点
def fun(n, k, startIndex): # 范围的第一个参数是变化的,因此设定参数startIndex
# 终止条件,长度为k的时候,收集
if len(path) == k:
res.append(path)
return
for i in range(startIndex, n+1):
# 将第一个值i加入到path中
path.append(i)
fun(n, k. i+1) # 这里的i+1,理解一下以上两个案例就知道了
# 递归之后的回溯过程,防止path累加
path.pop()
附上一道力扣的题目链接:理解后尝试一下自己实现这道题
组合问题