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

相关推荐
大圣编程1 小时前
面向对象深度理解
java·开发语言·算法
爱喝水的鱼丶1 小时前
SAP-ABAP:SAP 简单报表输出开发系列(共6篇) 第四篇:SAP 报表异常处理机制:数据校验与消息提示规范落地
开发语言·数据库·学习·算法·sap·abap
影寂ldy1 小时前
C# const 常量 / readonly 只读 / static readonly
java·开发语言·c#
C+-C资深大佬1 小时前
在PyCharm中创建虚拟环境的具体步骤是什么?
ide·python·pycharm
wabs6662 小时前
关于贪心算法【划分字母区间】的问题总结(C++语法)
算法·贪心算法
iCxhust2 小时前
c#多串口重量采集上位机程序
开发语言·汇编·c#·微机原理·8088单板机
QK_002 小时前
volatile 关键字核心作用
开发语言
Dxy12393102162 小时前
Python Tensor 向量入门:从零理解深度学习的“数据语言“
开发语言·python·深度学习
林森lsjs2 小时前
【日耕一题】3. 通过键盘输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。
java·开发语言