Python算法竞赛:排列组合核心用法

排列组合是算法竞赛、笔试面试的高频考点 ,核心区别:排列重顺序,组合不重顺序 。Python 自带标准库可快速解题,搭配回溯算法能覆盖所有变形场景。本文结合洛谷B2164组合数、洛谷P1706全排列、LeetCode77组合3道经典题,一站式搞定排列组合的内置函数用法与手写实现。

一、组合数计算:只求数量,不枚举(洛谷B2164)

题目核心

给定n、k,求C(n,k) mod 1e9+7(从n个元素选k个的方案数,顺序无关)。

数学公式

C(n,k)=n!/(k!*(n−k)!)

Python 极简解法(math.comb)

Python 3.10+ 提供math.comb直接计算组合数,搭配取模即可通过本题。

python 复制代码
from math import comb
MOD = 10**9 + 7

n, m = map(int, input().split())
# 直接计算组合数并取模
ans = comb(n, m) % MOD
print(ans)

样例输入 :5 3 → 输出:10

手写组合数(兼容低版本)

python 复制代码
def calc_comb(n, k):
    if k < 0 or k > n:
        return 0
    if k == 0 or k == n:
        return 1
    k = min(k, n - k)  # 减小计算量
    res = 1
    for i in range(1, k + 1):
        res = res * (n - k + i) // i
    return res

MOD = 10**9 + 7
n, m = map(int, input().split())
print(calc_comb(n, m) % MOD)

二、全排列生成:有序枚举所有序列(洛谷P1706)

题目核心

按字典序输出1~n的全排列,每个数字占5个字符宽度。

核心概念

排列 :元素顺序不同算不同结果,用itertools.permutations生成。

Python 标准库解法

python 复制代码
from itertools import permutations

n = int(input())
# 生成1~n的列表
nums = list(range(1, n + 1))
# 生成全排列
perms = permutations(nums)
# 按格式拼接:每个数字占5位
result = [''.join(f'{num:5d}' for num in p) for p in perms]
print('\n'.join(result))

样例输入:3 → 输出按要求对齐的6行全排列。

回溯手写全排列(竞赛必备模板)

python 复制代码
n = int(input())
res = []
used = [False] * (n + 1)  # 标记数字是否被使用

def backtrack(path):
    if len(path) == n:
        res.append(''.join(f'{x:5d}' for x in path))
        return
    for i in range(1, n + 1):
        if not used[i]:
            used[i] = True
            path.append(i)
            backtrack(path)
            path.pop()
            used[i] = False

backtrack([])
print('\n'.join(res))

三、组合枚举:生成所有k元子集(LeetCode77)

题目核心

给定n、k,返回1,n中所有k个数的组合(无序,不重复)。

标准库解法(itertools.combinations)

python 复制代码
from typing import List
from itertools import combinations

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        nums = list(range(1, n + 1))
        # 生成所有k元组合
        return [list(c) for c in combinations(nums, k)]

样例输入:n=4,k=2 → 输出6个组合。

回溯+剪枝(高效手写版)

组合无需顺序,用start避免重复,剪枝可大幅提速。

python 复制代码
from typing import List

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        res = []
        def backtrack(start, path):
            # 剪枝:剩余元素不够凑k个,直接返回
            if len(path) + (n - start + 1) < k:
                return
            if len(path) == k:
                res.append(path.copy())
                return
            for i in range(start, n + 1):
                path.append(i)
                backtrack(i + 1, path)  # 从下一个数开始,避免重复
                path.pop()
        backtrack(1, [])
        return res

四、核心对比:排列 vs 组合

类型 顺序 函数 典型场景
排列 permutations 排队、排序、序列
组合 combinations/comb 选人、选子集、方案数

快速选择指南

  1. 只求方案数 → 用math.comb(组合数)
  2. 生成所有有序序列 → 用permutations或全排列回溯
  3. 生成所有无序子集 → 用combinations或组合回溯
  4. 算法竞赛/面试 → 必须掌握回溯模板(内置函数可能受限)

总结

  1. 组合数:math.comb一步到位,搭配取模适配大数场景;
  2. 全排列:permutations快速生成,回溯可处理自定义约束;
  3. 组合枚举:combinations极简,回溯+剪枝更高效。

吃透这3道题与两套写法,Python 排列组合类题目直接秒杀。

相关推荐
Q26433650231 小时前
【有源码】基于 Hadoop 生态的化妆品销售数据存储分析与可视化 面向化妆品行业的用户画像构建与销售机会识别研究
大数据·hadoop·python·机器学习·spark·毕业设计·课程设计
2601_962078197 小时前
Python中calendar.weekday用法
python·编程技巧·calendar·日期处理·weekday
2601_962218617 小时前
万象生鲜系统业财一体化底层打通技术自动生成经营账单
大数据·数据库·人工智能·python·算法
2601_966949657 小时前
为什么量化策略需要大量历史股票数据?从回测可信度理解数据规模
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
niucloud-admin7 小时前
JAVA V6 多商户商城 开发文档——插件目录结构
java·开发语言
2601_962885727 小时前
如何用 Python 扫描 A 股跳空缺口并统计缺口回补概率?
java·前端·python
吞下星星的少年·-·7 小时前
The 2026 ICPC Asia East Continent Online Contest (II)(构造)
数据结构·算法
滕州市燕猫虎计算机科技工作室个体工商户7 小时前
Java锁
java·开发语言
李高钢8 小时前
Python FastAPI 框架入门:从零搭建你的第一个高性能 API 服务
数据库·python·fastapi