双指针法判断回文最直接高效,时间复杂度o(n)、空间复杂度o(1);纯比对直接首尾收缩,忽略非字母数字时需预处理;常见错误是循环条件写成i

用 std::string 双指针判断回文最直接
不需要额外空间,时间复杂度 O(n),适合大多数场景。核心是忽略大小写和非字母数字字符时才需预处理;纯字符串比对就直接首尾向中间收缩。
常见错误是循环条件写成 i 导致越界或重复比较,正确应为 <code>i :
bool isPalindrome(const std::string& s) {
int i = 0, j = s.length() - 1;
while (i
- 注意
s.length()返回size_t,减 1 后若 s 为空会回绕成极大值,所以空串要先判(或改用有符号索引) - 若需忽略空格/标点,别在原字符串上 erase——性能差;改用双指针跳过无效字符
- 大小写敏感?C++ 没有内置忽略大小写的比较函数,得手动转
std::tolower
用 std::equal + std::rbegin 一行解决
利用 STL 算法和反向迭代器,语义清晰、不易出错,但底层仍是遍历一半长度,性能与双指针相当。
典型误用是传入 s.begin() 和 s.end() 直接比,那是在比正序和正序,毫无意义:
bool isPalindrome(const std::string& s) {
return std::equal(s.begin(), s.begin() + s.size()/2, s.rbegin());
}
-
s.rbegin()对应末尾,s.rbegin() + k对应倒数第 k+1 个字符,所以不用手动算终点 - 当
s.size()为奇数时,中间字符自动被跳过,无需额外处理 - 该写法默认区分大小写;如需忽略,得配合自定义比较谓词,例如
[](char a, char b) { return std::tolower(a) == std::tolower(b); }
遇到 Unicode 字符(如中文、emoji)怎么办
C++ 标准库的 std::string 是字节序列,不是字符序列。一个 emoji 可能占 4 字节(UTF-8 编码),直接按 operator[] 下标访问会切裂码点,导致比较失败或崩溃。
- 纯 ASCII 字符串(英文、数字、基本符号)完全没问题;只要确认输入不包含 UTF-8 多字节字符,就不用升级
- 真要支持 Unicode,别手撸:用 ICU 库或 C++20 的
<unicode></unicode>(尚未广泛实现),或者先把 UTF-8 字符串解码为std::u32string再比 - 简单 hack 方式:用
std::wstring_convert<:codecvt_utf8>></:codecvt_utf8>(C++17 起已弃用,仅作过渡参考)
为什么不用 std::reverse 创建副本再比较
可以,但没必要。它分配新字符串、拷贝全部内容、再逐字符比,空间 O(n),且至少多一次完整遍历。
错误示范(新手常写):
std::string rev = s; std::reverse(rev.begin(), rev.end()); return s == rev;
- 当字符串很长(如几 MB 日志片段)时,内存开销和缓存不友好问题立刻暴露
- 短字符串(
- 如果只是判断、不需反转结果,这种写法属于典型“为了用 STL 而用 STL”
回文判断本身简单,难的是想清楚输入边界:是否含 Unicode、是否要过滤字符、性能敏感程度。没特殊需求,双指针最稳;图省事又不怕小开销,std::equal + rbegin 更少出错。其他方案,除非明确需要,否则先放一边。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











