当前位置: 首页 > article >正文

【C++经典例题】回文串判断:两种高效解法剖析

           💓 博客主页:倔强的石头的CSDN主页 

           📝Gitee主页:倔强的石头的gitee主页

            ⏩ 文章专栏:C++经典例题

                                  期待您的关注

1b7335aca73b41609b7f05d1d366f476.gif

目录

一、问题描述

示例

二、解法一:将字母数字连接到新的 string

思路

代码实现

代码解释

复杂度分析

三、解法二:直接原地筛选判断

思路

代码实现

代码解释

复杂度分析

总结


一、问题描述

在字符串处理中,判断一个字符串是否为回文串是一个经典问题。

本题有特殊要求:在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,如果短语正着读和反着读都一样,则认为该短语是一个回文串。字母和数字都属于字母数字字符。

示例

  • 输入: s = "A man, a plan, a canal: Panama",输出:true,解释:处理后得到 "amanaplanacanalpanama" 是回文串。
  • 输入:s = "race a car",输出:false,解释:处理后得到 "raceacar" 不是回文串。
  • 输入:s = " ",输出:true,解释:移除非字母数字字符后,s 是一个空字符串 "",空字符串正着反着读都一样,所以是回文串。

 原题链接 

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

二、解法一:将字母数字连接到新的 string

思路

这种方法的核心思想是先遍历原字符串,把其中的字母数字字符提取出来,同时将大写字母转换为小写字母,存储到一个新的字符串 tmp 中

然后再对新字符串 tmp 进行回文判断

代码实现

#include <iostream>
#include <string>

class Solution {
public:
    bool isPalindrome(string s) //第一种方式 将字母数字连接到新的string
    {
        string tmp;
        string::iterator left = s.begin();
        string::iterator right = s.end();

        while (left != right)//第一次遍历,所有字母数字转入新string,并且统一为小写
        {
            if ((*left >= '0' && *left <= '9') || (*left >= 'a' && *left <= 'z'))
                tmp += *left;
            if (*left >= 'A' && *left <= 'Z')
                tmp += (*left + 32);
            ++left;
        }

        if (tmp.empty())//如果新string为空,则判定为回文串
            return true;

        left = tmp.begin();
        right = tmp.end() - 1;
        while (left <= right)//第二次遍历 左右迭代器逐个对比
        {
            if (*left == *right)
            {
                ++left;
                --right;
            }
            else
                return false;
        }
        return true;
    }
};

代码解释

  1. 提取字母数字并转换大小写
    • 定义一个空字符串 tmp 用于存储处理后的字符。
    • 使用迭代器 left 遍历原字符串 s,当遇到数字('0' 到 '9')或小写字母('a' 到 'z')时,直接添加到 tmp 中;当遇到大写字母('A' 到 'Z')时,将其 ASCII 码值加 32 转换为小写字母后添加到 tmp 中。
  2. 处理空字符串情况:如果 tmp 为空字符串,根据题目定义,空字符串是回文串,直接返回 true
  3. 回文判断:使用双指针法,left 指向 tmp 的开头,right 指向 tmp 的结尾,逐个比较对应位置的字符。如果不相等,返回 false;如果都相等,最终返回 true

复杂度分析

  • 时间复杂度:O(n)需要遍历原字符串一次,再遍历新字符串一次。
  • 空间复杂度:O (n),其中  n是处理后新字符串的长度。

三、解法二:直接原地筛选判断

思路

这种方法不创建新的字符串,而是直接在原字符串上使用双指针法进行筛选和判断。通过两个指针 left 和 right 分别从字符串的两端开始向中间移动,跳过非字母数字字符,同时将字符转换为小写后进行比较。

代码实现

#include <iostream>
#include <string>
#include <cctype>

class Solution {
public:
    bool isPalindrome(std::string s) //第二种方式,直接原地筛选判断
    {
        string::iterator left = s.begin();
        string::iterator right = s.end() - 1;

        while (left < right)
        {
            // 跳过左边的非字母数字字符
            while (left < right && !isalnum(*left))
            {
                ++left;
            }
            // 跳过右边的非字母数字字符
            while (left < right && !isalnum(*right))
            {
                --right;
            }

            if (left < right) {
                // 将字符转换为小写后比较
                if (tolower(*left) != tolower(*right))
                {
                    return false;
                }
                ++left;
                --right;
            }
        }
        //跳出循环,要么left==right,要么left>right 
        //说明所有需要比较的字符对都已经检查过,且都相等
        return true;
    }
};

代码解释

  1. 初始化指针:使用迭代器 left 指向字符串的开头,right 指向字符串的结尾。
  2. 跳过非字母数字字符:通过两个内层 while 循环,分别将 left 和 right 指针移动到字母数字字符的位置。
  3. 字符比较:将 left 和 right 指针指向的字符转换为小写后进行比较,如果不相等,返回 false;如果相等,继续移动指针。
  4. 返回结果:当 left 大于等于 right 时,说明所有需要比较的字符对都已经检查过,且都相等,返回 true

复杂度分析

  • 时间复杂度:O(n),只需要遍历一次字符串。
  • 空间复杂度:O(1),只使用了常数级的额外空间。

总结

两种解法都能有效解决回文串判断问题:

解法一逻辑清晰,易于理解,但需要额外的空间存储处理后的字符串;

解法二原地操作,空间复杂度更低,更适合处理大规模数据。在实际应用中,可以根据具体需求选择合适的解法。


http://www.kler.cn/a/568777.html

相关文章:

  • k8s 中各种发布方式介绍以及对比
  • 本地部署SenseVoice(包括离线设备操作)
  • Java语法基础知识点2
  • 达梦数据库系列之Mysql项目迁移为达梦项目
  • 基于html的俄罗斯方块小游戏(附程序)
  • 技术问题汇总:前端怎么往后端传一个数组?
  • DeepSeek 与大数据治理:AI 赋能数据管理的未来
  • 第十五届蓝桥杯最后一题 拔河问题
  • 各种传参形式
  • 深入探索 STM32 微控制器:从基础到实践
  • 每日一题——接雨水
  • 2.Exercise
  • 关于时间序列预测
  • 3.16 AI Agent 技术全景解析:从核心能力到企业级应用实践
  • GPT-4.5震撼登场,AI世界再掀波澜!(3)
  • Tkinter和爬虫写的知乎回答下载exe【免费下载】
  • 【STM32F103ZET6——库函数】6.PWM
  • 【软件安装】非华为手机安装华为电脑管家(14.0.5.8 C233)(附带安装包下载地址)
  • 蜈蚣博弈(Centipede Game)
  • Oracle性能调优(一):时间模型统计