给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。
示例: 输入: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
完整代码如下:
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
result = [] # 存放结果集
self.backtracking(n, k, 1, [], result)
return result
def backtracking(self, n, k, startIndex, path, result):
if len(path) == k:
result.append(path[:])
return
for i in range(startIndex, n - (k - len(path)) + 2): # 优化的地方
path.append(i) # 处理节点
self.backtracking(n, k, i + 1, path, result)
path.pop() # 回溯,撤销处理的节点
def combine(self, n: int, k: int) -> List[List[int]]:
result = [] # 存放结果集
self.backtracking(n, k, 1, [], result)
return result
combine
方法是程序的入口函数。result
是一个空列表,用来存储所有符合条件的组合结果。backtracking
方法来执行递归和回溯操作,从数字 1
开始,逐步构建组合。def backtracking(self, n, k, startIndex, path, result):
if len(path) == k:
result.append(path[:])
return
for i in range(startIndex, n - (k - len(path)) + 2): # 优化的地方
path.append(i) # 处理节点
self.backtracking(n, k, i + 1, path, result)
path.pop() # 回溯,撤销处理的节点
递归终止条件:
if len(path) == k
: 如果当前路径 path
的长度达到了 k
,表示已经形成了一个完整的组合。result.append(path[:])
: 将当前组合的副本加入到 result
中。return
: 结束当前递归。循环部分:
for i in range(startIndex, n - (k - len(path)) + 2)
: 这是一个循环,用来尝试从 startIndex
到 n
的每一个数字作为组合的一部分。这里的范围设置是一个优化点,确保循环不会无意义地执行。
n - (k - len(path)) + 2
确保了剩下的数字足够填满组合。例如,如果 k
是 3,而当前 path
中已经有 2 个数字,那么剩下的空间只能容纳 1 个数字,因此 i
不需要遍历到 n
。处理节点:
path.append(i)
: 将当前数字 i
加入到路径 path
中。递归调用:
self.backtracking(n, k, i + 1, path, result)
: 递归地处理下一个数字,startIndex
更新为 i + 1
,表示下一个组合元素只能从 i
之后的数字中选取。回溯:
path.pop()
: 在递归返回后,将当前数字 i
从路径 path
中移除,恢复到递归前的状态,进行下一轮循环。这一步是“回溯”的核心操作。