LeetCode 125 验证回文串

1. 题目

125. 验证回文串 - 力扣(LeetCode)

题目描述3

给定一个字符串 s ,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

本题中,将空字符串定义为有效的回文串。

示例

输入:s = "A man, a plan, a canal: Panama"

输出:true

解释:"amanaplanacanalpanama" 是回文

输入:s = "race a car"

输出:false

输入:s = " "

输出:true

约束

  • (1 <= s.length < 2 *10^5)

  • s 仅由可打印的 ASCII 字符组成

2. 最佳解题思路描述(原地双指针,O (1) 空间最优)

  1. 左指针 l 从头部、右指针 r 从尾部向中间靠拢;

  2. 左指针跳过所有非字母数字字符,右指针同理;

  3. 左右指针都定位到有效字符后,统一转为小写比较:

    • 不相等 → 直接返回 false;

    • 相等 → l++、r--,继续向内收缩;

  4. 两指针相遇 / 交叉说明全部匹配,返回 true。

优势

无需新建过滤后的字符串,原地操作,空间复杂度 (O(1));一次遍历即可完成,效率更高。

3. 我的代码(逻辑正确可 AC,但额外开辟字符串,空间非最优)

复制代码
class Solution {
public:
    bool isPalindrome(string s) {
        string s1;
        for(int i = 0;i<s.size();i++){
            if(s[i]>='A'&&s[i]<='Z'){
                s1+=s[i]+32;
            }
            if(s[i]>='a'&&s[i]<='z'){
                s1+=s[i];
            }
            if(s[i]>='0'&&s[i]<='9'){
                s1+=s[i];
            }
        }
        cout<<s1<<endl;
        int len = s1.size();
        bool flag = true;
        for(int i = 0;i<len/2;i++){
            if(s1[i]!=s1[len-i-1]){
                flag = false;
                break;
            }
        }
        return flag;
    }
};

代码说明

  1. 正确性:逻辑无 bug,能通过全部测试用例;

  2. 存在缺陷与优化点:

    • 额外创建字符串s1存储过滤、小写后的字符,空间 (O(n)),大数据量占用更多内存;

    • 存在调试输出 cout<<s1<<endl;,提交前必须删除,否则判题会输出多余内容报错;

    • 判断字符区间写法繁琐,可使用库函数 isalnum() 一键判断是否为字母数字;

    • 大写转小写 +32 依赖 ASCII 编码,可读性差,标准函数 tolower() 更规范;

    • 变量flag可省略,字符不等直接 return false 提前终止循环。

4. 最优标准代码(原地左右双指针,O (1) 空间)

复制代码
#include <cctype>
class Solution {
public:
    bool isPalindrome(string s) {
        int l = 0, r = s.size() - 1;
        while (l < r) {
            // 左指针跳过非字母数字
            while (l < r && !isalnum(s[l])) l++;
            // 右指针跳过非字母数字
            while (l < r && !isalnum(s[r])) r--;
            // 统一转小写对比
            if (tolower(s[l]) != tolower(s[r])) {
                return false;
            }
            l++;
            r--;
        }
        return true;
    }
};

5. 总结

  1. 你的过滤新建字符串写法思路简单、容易理解,但空间开销大,面试优先使用双指针原地方案;

  2. 关键工具函数:isalnum(c) 判断是否字母 / 数字,tolower(c) 统一小写;

  3. 必须删除调试用 cout 输出,否则在线判题会出错;

  4. 回文判断核心:对称位置字符忽略大小写相等,非字母数字直接忽略。

6. 相关知识拓展

拓展 1:基于原代码的优化版本(保留过滤字符串,去除冗余)

复制代码
#include <cctype>
class Solution {
public:
    bool isPalindrome(string s) {
        string t;
        for (char c : s) {
            if (isalnum(c)) {
                t += tolower(c);
            }
        }
        int n = t.size();
        for (int i = 0; i < n / 2; ++i) {
            if (t[i] != t[n - i - 1]) return false;
        }
        return true;
    }
};

拓展 2:字符判断底层原理

  • isalnum(c):返回 true 当且仅当 c 是大小写字母或数字;

  • 大写字母 ASCII 比对应小写小 32,A-Z +32 = a-z,仅字母适用,数字不能加减 32 转换。

拓展 3:复杂度对比

  1. 过滤新建字符串(你的写法):时间 (O(n)),空间 (O(n));

  2. 原地双指针最优解:时间 (O(n)),空间 (O(1));

拓展 4:易错点复盘

  1. 忘记过滤符号、空格,直接对比原字符串字符;

  2. 大小写未统一,导致 'A' 和 'a' 判定不相等;

  3. 保留 cout 调试输出,在线 OJ 判题失败;

  4. 双指针内层跳过字符时忘记加l<r边界,指针越界。

相关推荐
Asize7 小时前
146. LRU 缓存
算法
Asize7 小时前
543. 二叉树的直径
算法
lemon_sjdk7 小时前
ObjectProperty
java·开发语言·算法
Zentceh8 小时前
AI-ISP在夜视机芯中的应用:从传统ISP到PixelClean全彩夜视的进化
人工智能·科技·算法·计算机视觉·车载系统·视频·智能硬件
xier_ran8 小时前
【infra之路】AWQ 详解:激活感知权重保护,让 W4A16 量化精度超越 GPTQ
线性代数·算法·机器学习·量化·infra
亦皓ai8 小时前
AI时代后端工程(二):AI把代码写得越来越快,我却越来越不敢让它直接开工了
人工智能·算法·机器学习·搜索引擎·transformer
玖玥拾10 小时前
LeetCode 392 判断子序列
笔记·算法·leetcode
重生之后端学习11 小时前
239. 滑动窗口最大值[困难]✅
java·数据结构·算法·leetcode·职场和发展
fpcc11 小时前
算法和数据结构—动态规划法
数据结构·算法·动态规划