必须先排序,因为std::next_permutation仅生成字典序下一个排列,起点必须是最小字典序(升序)才能遍历全部;未排序会跳过前置排列,且重复元素下仍能自动去重。

std::next_permutation 为什么必须先排序?
它只生成“字典序下一个”排列,不是从头开始枚举全部。如果输入是 {3,1,2},调用一次 std::next_permutation 得到的是 {3,2,1},再调用返回 false —— 因为 {3,2,1} 已是字典序最大,没有“下一个”。想遍历全部 6 种排列,得从最小字典序(即升序)开始。
- 正确起点:
std::sort(v.begin(), v.end()) - 错误起点:任意乱序后直接调用,大概率漏掉前面大量排列
- 底层依赖:
operator 或自定义比较函数,所以元素类型必须支持比较
如何完整遍历所有唯一排列(含重复元素)?
当容器中有重复值(如 {1,1,2}),std::next_permutation 仍能正确跳过重复排列,前提是初始状态已排序。它内部按字典序推进,天然去重 —— 不需要 std::set 或额外判重逻辑。
- 输入
{1,1,2},排序后为{1,1,2} - 依次得到:
{1,1,2}→{1,2,1}→{2,1,1},共 3 种(而非 6 种) - 若未排序(如起始为
{1,2,1}),第一次调用就跳到{2,1,1},直接丢失前两个 - 注意:去重仅发生在生成过程中,不改变原容器内容
返回值 false 到底意味着什么?
它只表示“当前排列已是字典序最大”,不是“出错”或“越界”。常见误用是忽略返回值、或在循环中错误地多执行一次。
- 标准写法是 do-while 或 while,且把
next_permutation放在 while 条件里:
std::sort(v.begin(), v.end());
do {
// 处理当前排列 v
} while (std::next_permutation(v.begin(), v.end()));
false 后,容器恢复为升序(最小排列),可再次用于新一轮遍历性能和容器类型要注意什么?
时间复杂度平均 O(n),最坏 O(n),单次调用很快;但全量遍历仍是 O(n! × n),只适用于 n ≤ 10 左右。另外,它要求随机访问迭代器。
- 支持:
std::vector、std::array、原生数组(传指针) - 不支持:
std::list、std::forward_list(无随机访问) - 不能用于 const 容器,因为会修改元素位置
- 若需保留原始顺序,处理前先拷贝一份
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











