std::next_permutation要求输入为升序起始态,因其按字典序找下一个排列,若起始非升序(如"cba")则首次调用即返回false;正确做法是先sort再do-while循环。

next_permutation 为什么只对已排序序列有效
std::next_permutation 不是“生成所有排列”,而是“在当前排列基础上,按字典序找下一个”。它依赖当前状态——如果输入不是升序起始态(比如 "cba"),第一次调用就可能直接返回 false,后续排列全漏掉。常见错误是传入乱序字符串后反复调用,结果只输出一两个排列就停了。
正确做法是先用 std::sort 排好,再进循环:
std::string s = "bca";
std::sort(s.begin(), s.end()); // 变成 "abc"
do {
std::cout <h3>字符重复时 next_permutation 还能用吗</h3><p>能,而且它天然去重。比如 <code>"aab"</code>,<code>std::next_permutation</code> 生成的 3 个排列是:<code>"aab"</code>、<code>"aba"</code>、<code>"baa"</code>,不会出现重复项。这是因为它内部比较逻辑基于“严格弱序”,遇到相同字符会跳过等价交换。</p><p>但注意:如果你手动实现或用其他库(比如 Python 的 <code>itertools.permutations</code>),默认不判重,必须额外套 <code>set</code>。C++ 标准库这点很省心。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div><p>验证方式很简单:</p><pre class="brush:php;toolbar:false;">std::string s = "aab";
std::sort(s.begin(), s.end());
int cnt = 0;
do { ++cnt; } while (std::next_permutation(s.begin(), s.end()));
// cnt == 3,不是 6next_permutation 对宽字符或自定义类型的支持
它不限于 std::string,只要迭代器指向的元素支持 operator,就能用。比如 <code>std::vector<wchar_t></wchar_t>、std::wstring,甚至 std::vector<int></int> 都可以:
-
std::next_permutation本质操作的是迭代器区间,和容器类型无关 - 中文 UTF-8 字符串不能直接用——因为一个汉字占多个
char,std::string按字节排,会把汉字拆开乱序;得先转成std::wstring或 Unicode 码点向量 - 自定义结构体需提供
operator,且保证严格弱序(比如不能只比一个字段,忽略其他)
性能和边界要注意什么
全排列时间复杂度是 O(n!),std::next_permutation 单次调用均摊 O(1),但总循环仍是指数级。实际使用中容易卡死的点有:
- 对长度 ≥ 12 的字符串调用,排列数超 4.7 亿,基本跑不完
- 传入空字符串或单字符:
next_permutation返回false,循环体一次都不进,这是符合预期的 - 迭代器范围写错,比如用
s.begin()和s.end() - 1,会漏掉最后一个字符参与排列 - 多线程里共享同一字符串并调用
next_permutation?别这么做——它会原地修改,没锁就是数据竞争
真正要处理长序列的字典序枚举,得换思路:用回溯剪枝、或生成指定 rank 的排列(std::nth_element 不适用,得手写康托展开),而不是硬跑 next_permutation。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










