开会员与付费前请必须阅读这篇文章,在首页置顶第一篇:(进站必看本站VIP介绍/购买须知)
本站所有源码均为自动秒发货,默认(百度网盘)
本站所有源码均为自动秒发货,默认(百度网盘)
在算法和日常开发中,组合(Combination) 是一个非常经典的问题:给定一个数组,从中选出
k 个元素,输出所有不重复的选取结果。组合和排列不同,组合不考虑元素顺序,比如
[1,2] 和 [2,1] 算同一个组合,只需要输出一次。这篇文章会用通俗易懂的方式讲解组合生成的核心思路,并提供可直接运行、通用博客格式的代码,适合新手学习和面试准备。
一、什么是组合问题?
举个例子:
数组 [1,2,3],选取 k=2 个元素的所有组合为:
plaintext
[1,2]
[1,3]
[2,3]
核心规则:
- 不重复选取元素
- 不考虑顺序
- 结果是所有长度恰好为
k的子集合
二、核心解题思路:回溯法
生成组合最常用、最容易理解的方法是回溯算法,可以理解为:
- 一步一步选元素
- 选够
k个就保存结果 - 回退一步,尝试下一个可能的选项
- 直到遍历完所有可能
简单流程:
- 从数组的第
start位开始选数 - 把当前数加入临时列表
- 递归选取下一个数(起始位置 + 1,避免重复)
- 临时列表长度 = k 时,记录结果
- 回溯:移除最后一个数,继续尝试其他可能
三、完整可运行代码
我用Python实现,代码简洁、通用,可直接复制到大多数博客平台使用。
Python 实现(回溯法)
python
运行
def generate_combinations(nums, k):
"""
从数组nums中生成所有k个元素的组合
:param nums: 原始数组
:param k: 选取元素的数量
:return: 所有组合的列表
"""
result = [] # 存储最终结果
# 回溯函数:path=当前选择的路径,start=起始索引
def backtrack(path, start):
# 递归终止条件:路径长度等于k,保存结果
if len(path) == k:
result.append(path.copy())
return
# 从start开始遍历,避免重复组合
for i in range(start, len(nums)):
path.append(nums[i]) # 选择当前元素
backtrack(path, i + 1) # 递归选取下一个元素
path.pop() # 回溯,撤销选择
# 开始回溯
backtrack([], 0)
return result
# 测试示例
if __name__ == "__main__":
# 测试用例1
arr1 = [1, 2, 3]
k1 = 2
print("数组", arr1, "选取", k1, "个元素的组合:")
for c in generate_combinations(arr1, k1):
print(c)
print("-" * 30)
# 测试用例2
arr2 = ["A", "B", "C", "D"]
k2 = 3
print("数组", arr2, "选取", k2, "个元素的组合:")
for c in generate_combinations(arr2, k2):
print(c)
四、代码运行结果
plaintext
数组 [1, 2, 3] 选取 2 个元素的组合:
[1, 2]
[1, 3]
[2, 3]
------------------------------
数组 ['A', 'B', 'C', 'D'] 选取 3 个元素的组合:
['A', 'B', 'C']
['A', 'B', 'D']
['A', 'C', 'D']
['B', 'C', 'D']
五、代码关键说明
-
start参数的作用每次从
i+1开始选,保证不会出现[2,1]这种重复顺序的组合,这是组合问题的关键。 -
回溯(
pop())递归返回后,把最后加入的数删掉,才能继续尝试同层的下一个选项。
-
通用性
代码支持数字、字符串等任意类型数组,无需修改即可使用。
六、扩展:使用标准库快速生成
如果你在工程中不想手写回溯,可以用 Python 内置的
itertools.combinations,一行代码搞定:python
运行
import itertools
nums = [1,2,3]
k = 2
result = list(itertools.combinations(nums, k))
print(result) # [(1,2), (1,3), (2,3)]
注意:面试时必须手写回溯法,不能直接调库!
七、适用场景
- 面试算法题:组合总和、子集、全组合
- 开发场景:权限组合、商品套餐组合、筛选条件组合
- 算法基础:回溯法入门经典例题
总结
- 组合生成 = 回溯法 + 控制起始位置
- 不重不漏的关键:从
i+1开始递归 - 代码简洁通用,适合学习和直接使用