std::sort 最快且直观,但需先检查长度是否相等,并确保字符串可修改;ASCII 场景可用 128 元素频次数组实现 O(n);任意字符集推荐 std::unordered_map,注意空字符和哈希性能;业务定义决定是否预处理大小写与空格。

用 std::sort 最快写出来,但要注意字符串是否可修改
如果允许修改原字符串,std::sort 是最直观的解法:把两个字符串分别排序,再比较是否相等。时间复杂度 O(n log n),常数小,实测在中等长度(几百字符内)非常快。
常见错误是忽略长度判断——长度不同直接不是变位词,必须先检查:
if (s1.length() != s2.length()) return false;
否则排序后比较会浪费计算。另外注意:传入 std::sort 的必须是非 const 迭代器,所以不能对字面量或 const std::string& 直接排,得先拷贝:
- 用
std::string s1_copy = s1;再std::sort(s1_copy.begin(), s1_copy.end()); - 别写
std::sort(s1.begin(), s1.end())然后传const std::string&,编译不过
用字符频次数组,适合 ASCII 字符串且追求 O(n)
如果确定字符串只含 ASCII 字符(0–127),用长度为 128 的整型数组计数,遍历一遍 s1 自增,遍历一遍 s2 自减,最后检查数组是否全零。这是真正的线性时间,无排序开销。
立即学习“C++免费学习笔记(深入)”;
关键细节:
- 必须初始化数组为 0:
int count[128] = {};,不然有脏值 - 访问前要确认字符值在范围内,比如
static_cast<unsigned char>(c)</unsigned>防止负值下标越界(char在某些平台默认 signed) - 不适用于 Unicode(如 UTF-8 多字节字符),此时需改用
std::unordered_map<char int></char>,但会有哈希开销和内存分配
用 std::unordered_map 处理任意字符集,但小心空字符和性能抖动
当字符串可能含任意 char 值(包括 '\0')或你不确定编码时,std::unordered_map 更稳妥。逻辑和频次数组一致,只是底层是哈希表。
容易踩的坑:
- 别漏掉长度检查,否则
"a"和"aa"可能因 map 大小相同而误判 -
std::unordered_map::operator[]会隐式插入默认值(0),导致 map size 增大;建议用find()+at()或手动判断键存在性 - 极端情况下(大量哈希冲突)查找退化为
O(n),不过对普通字符串影响不大
区分大小写和空白符?这取决于你的业务定义
“变位词”本身没有标准定义,C++ 不会自动帮你忽略空格或转小写。如果你的需求是“忽略大小写、忽略空格”,必须显式预处理:
auto normalize = [](std::string s) {
s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
return s;
};
然后对 normalize(s1) 和 normalize(s2) 判变位词。这里 ::isspace 和 ::tolower 是 C 风格函数,注意它们对 char 的符号敏感——传入负值可能导致未定义行为,所以仍推荐先转 unsigned char。
真正难的不是选哪种方法,而是想清楚:你处理的是纯 ASCII 标识符?用户输入的自然语言?还是日志里的混合文本?不同场景下,“相等”的定义变了,算法就得跟着调。


















