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 排列组合类题目直接秒杀。

相关推荐
IT小盘几秒前
16-Prompt版本管理-从手工修改到可追踪配置系统
开发语言·人工智能·python·prompt
卷无止境2 分钟前
Python进程池那些事儿:从原理到实战
后端·python
满怀冰雪2 分钟前
15-Paddle 高层 API 入门:paddle.Model 的训练与评估流程
人工智能·python·深度学习·机器学习·paddle
happyprince4 分钟前
篇2-bitsandbytes-具体观-算法与实现剖析
算法
johnny2334 分钟前
Python生态调试库:IceCream、birdseye、peek、qj、crab_dbg、spewer
python
Cx330❀8 分钟前
【Linux网络】深入 HTTP 协议(五):从 Cookie/Session 原理到 C++ 源码实战
linux·运维·服务器·开发语言·网络·c++·http
鸿芯微控科技10 分钟前
MFC气体转换系数怎么用?标定气体、换算方向与Python批量计算
c++·python·mfc
北冥you鱼13 分钟前
Go语言四则运算实战:从基础类型到big包的深度解析
开发语言·后端·golang
江畔柳前堤8 小时前
roLabelImg 详细安装教程
开发语言·人工智能·后端·云原生
0566468 小时前
agent学习Day15——SQLAlchemy 查询过滤、分页与历史列表接口
python·学习·fastapi