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

相关推荐
兵慌码乱11 小时前
面向桌面端的资产管理系统分层架构设计与核心模块实现
python·系统架构·sqlite·pyqt5·数据库设计·桌面应用开发·mvc架构
hboot13 小时前
AI工程师第三课 - 机器学习基础
python·scikit-learn·kaggle
To_OC16 小时前
LC 1 两数之和:面试第一道必考题,暴力解法直接被面试官 pass
javascript·算法·leetcode
顾林海18 小时前
Agent入门阶段-编程基础-Python:流程控制
python·agent·ai编程
鱼鱼不愚与20 小时前
《原来如此 | 第01期:为什么导航软件能预测红绿灯倒计时?》
算法
呱呱复呱呱20 小时前
Django CBV 源码解读:一个请求是怎么找到你的 get() 方法的
python·django
复杂网络1 天前
论最小 Agent 计算机的形态
算法
曲幽1 天前
刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API
python·fastapi·web·translate·goldendict·libretranslate·stardict·pystardict
荣码1 天前
用Streamlit给AI应用套个界面,10行代码出Web页面
java·python