std::sort排序法最快且直观:先检查长度,再复制字符串后排序比较;字符频次数组法O(n)更优,但需确保字符范围合法并统一大小写。

用 std::sort 最快写出来,但要注意字符串是否可修改
如果允许原地修改两个字符串,std::sort 是最直观的解法:排序后直接比较。时间复杂度 O(n log n),常数小,实际跑得很快。
常见错误是传入 const std::string& 后试图排序——编译不过,因为 std::sort 需要随机访问迭代器且要求可写。
- 先检查长度是否相等,不等直接返回
false - 用
std::string的副本(如s1_copy = s1)再排序,避免破坏原始输入 - 别对
std::string_view或字面量直接排序,它们不提供非 const 迭代器
std::string s1_copy = s1, s2_copy = s2; std::sort(s1_copy.begin(), s1_copy.end()); std::sort(s2_copy.begin(), s2_copy.end()); return s1_copy == s2_copy;
用字符频次数组,适合 ASCII 字符串且追求 O(n)
当确定字符串只含小写英文字母('a'–'z'),用长度为 26 的 int 数组计数,是真正线性、无额外比较开销的方案。
容易踩的坑是越界访问:用 s[i] - 'a' 前没校验 s[i] 是否在范围内,遇到空格或大写字母会崩。
立即学习“C++免费学习笔记(深入)”;
- 务必先做长度判断,省去后续所有计算
- 遍历第一个字符串时递增计数,第二个字符串递减;最后检查数组是否全为 0(或边减边判断负值提前退出)
- 若字符串可能含大小写混合,统一转成小写(
std::tolower)再处理,注意 locale 影响
if (s1.length() != s2.length()) return false;
int count[26] = {0};
for (char c : s1) count[c - 'a']++;
for (char c : s2) {
if (--count[c - 'a'] < 0) return false;
}
return true;用 std::unordered_map 处理 Unicode 或泛型字符
一旦字符串可能含中文、emoji 或宽字符(char32_t),数组方案失效,必须用哈希表。但要注意:C++ 标准库不支持直接用 char32_t 做 std::unordered_map 键,需手动提供哈希函数或改用 std::map。
性能上,std::unordered_map 平均 O(n),但哈希碰撞和内存分配开销比数组大;std::map 是 O(n log k)(k 是不同字符数),对短字符串反而更稳。
- 别用
std::string::at()循环取字符——UTF-8 下会错切字节;应先用std::utf8::decode(C++20)或第三方库提取码点 - 如果只是判别 ASCII 扩展字符(如 Latin-1),仍可用
unsigned char转整数作键,避免符号扩展问题 - 清空 map 比重置数组慢,重复调用时建议复用对象并调用
.clear()
为什么不用 std::is_permutation?
std::is_permutation 看似完美匹配需求,但它最坏复杂度是 O(n²),且标准未规定实现细节——某些 STL 实现会先尝试快速路径(如 hash),但不可靠。更关键的是:它不跳过长度检查,也不处理 const 输入的约束,容易误用。
- 它接受两个范围,但内部可能做多次遍历,对长字符串明显不如手写频次法
- 若传入
std::string::c_str(),得到的是const char*,无法满足部分重载要求,编译失败 - 没有 early-return 机制:即使开头就发现字符频次不匹配,它仍可能继续比对
除非代码极度强调可读性且字符串极短(


















