用std::next_permutation不漏解需先排序再do-while循环;它自动去重且性能优于手写回溯;string上swap失效多因传值或const引用。
std::next_permutation 怎么用才不漏解
直接用
是最稳妥的全排列实现方式,前提是输入序列初始为升序(或严格弱序)。它只生成字典序下一个排列,如果起始不是最小序,会跳过前面所有排列。
必须先对字符串排序:
,否则第一次调用就可能返回
循环条件写成
,不能用
前置判断,否则会丢掉原始排列
重复字符也能正确去重——只要容器元素支持
内部自动跳过等价排列
手写递归回溯时 vector
& res 传参为什么总为空
常见错误是把结果容器按值传递(
),每次递归都拷贝一份,修改的只是副本,上层看不到新增排列。
必须传引用:
递归终止条件别写成
,应该是
,否则最后一个字符没参与交换,少一层分支
交换后记得回溯还原:
后必须再 swap 一次,否则后续分支基于脏状态运行
去重逻辑不能只靠
——这只有在已排序前提下才有效;若未排序,得用
记录本轮用过的首字符
有重复字符时 std::next_permutation 和手动回溯性能差多少
两者时间复杂度都是 O(n! × n),但常数差异明显:
是高度优化的底层实现,单次调用平均 O(1);而手写回溯每层都要遍历、判重、swap,实际慢 2–3 倍。
重复字符越多,手动回溯的剪枝收益越小——因为
本身已内置等价跳过逻辑
若只需计数不需要存结果,用
配合计数器比构造所有字符串快一个数量级
注意:
要求随机访问迭代器,
不支持,必须用
或
为什么 swap(s[i], s[j]) 在 string 上有时不生效
的
返回的是
,swap 本身没问题。问题多出在:传入的是
值参,或用了
,或误用
(抛异常不改内容)。
立即学习
“
C++免费学习笔记(深入)
”;
确保参数是
,不是
或
避免用
—— 返回 const char*,无法赋值
调试时打印
地址,确认每次递归操作的是同一块内存,而不是意外拷贝
实际写的时候,重复字符处理和引用传递这两个点,最容易在深夜调试时反复卡住。
std::next_permutationstd::sort(s.begin(), s.end())falsedo { ... } while (std::next_permutation(s.begin(), s.end()))while 比较,next_permutationvector res void dfs(string& s, int i, vector& res) i == s.length() - 1i == s.length()swap(s[i], s[j]);if (j > i && s[j] == s[j-1]) continue;setnext_permutationnext_permutationstd::next_permutationnext_permutationstd::liststd::stringstd::vectorstd::stringoperator[]char&stringconst string&s.at(i)string& sconst string&strings.c_str()[i]s.data()