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

相关推荐
To_OC8 小时前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode
学测绘的小杨13 小时前
CompassFusion:一个从 GNSS 到 GNSS/INS 组合导航的独立工程包
python
用户9385156350713 小时前
从 O(n²) 到 O(nlogn):一文读懂快速排序的“快”与“妙”
javascript·算法
To_OC14 小时前
手写快排次次翻车?别死背快排模板了,这才是面试官想听的底层逻辑
javascript·算法·排序算法
饼干哥哥15 小时前
Reddit VOC调研太慢?搭一个AI专家团队半小时洞察任何品类|以猫用饮水机为例
人工智能·算法·ai编程
地平线开发者16 小时前
Transformer模型部署之性能优化指南
算法
地平线开发者17 小时前
人在途中:从“编译失败”到“模型可落地”——CUDA 自定义算子
算法·自动驾驶
半个落月19 小时前
从递归到快速排序:用 JavaScript 把分治思想讲明白
javascript·算法·面试
zzzzzz31020 小时前
当产品经理说这个很简单:我用Python自动化处理奇葩需求的实战指南
python·pycharm·产品经理
雪隐20 小时前
个人电脑玩AI-06让5060 Ti给你打工——不光能画画,Qwen3-TTS还能学人说话,连我老板都信了!
人工智能·后端·python