有效回文OJ

Valid palindrome OJ

本文关键字:OJ 回文 有效      更新时间:2023-10-16

给定一个字符串,确定它是否是回文,只考虑字母数字字符,忽略大小写。例如"一个人,一个计划,一条运河:巴拿马"是一个回文。"赛车"不是一个回文。

class Solution {
public:
    bool isPalindrome(string s) {
        if (!s.length()) return true;
        int i = 0, j = s.length() - 1;
        for (int k = 0; k < j; ++k)
            s[k] = tolower(s[k]);
        while (i < j) {
            if ((s[i] < 48)||(s[i] > 57 && s[i] < 97)||(s[i] > 122))
                ++i;
            else if ((s[j] < 48)||(s[j] > 57 && s[j] < 97)||(s[j] > 122))
                --j;
            else if (s[i++] != s[j--]) return false;
        }
        return true;
    }
};
错误答案:输入:"!bHvX!?!!vHbX"输出:true应为:false

它怎么了?

不要使用"幻数"。考虑到除了ASCII之外还有EBCDIIC编码方案。

我会用以下方式编写函数

#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>
bool IsPalindrome( const std::string &s )
{
    std::string::size_type i = 0, j = s.length();
    do
    {    
            while ( i != j && !std::isalnum( s[i] ) ) ++i;
            while ( j != i && !std::isalnum( s[--j] ) );
    } while ( i != j && std::toupper( s[i] ) == std::toupper( s[j] ) && ++i );

//  Unit test:)
//  std::cout << "i = " << i << ", j = " << j << std::endl;
    return ( i == j );
}
int main() 
{
    std::string s( "A man, a plan, a canal: Panama" );
    std::cout << '"' << s << "" is palindrome: " 
              << std::boolalpha << IsPalindrome( s ) << std::endl;
    s = "race a car";
    std::cout << '"' << s << "" is palindrome: " 
              << std::boolalpha << IsPalindrome( s ) << std::endl;
    s = "!bHvX!?!!vHbX";
    std::cout << '"' << s << "" is palindrome: " 
              << std::boolalpha << IsPalindrome( s ) << std::endl;

    return 0;
}

输出为

"A man, a plan, a canal: Panama" is palindrome: true
"race a car" is palindrome: false
"!bHvX!?!!vHbX" is palindrome: false

您可以将该函数作为类的运算符函数。例如

struct Solution
{
   bool operator ()( const std::string & ) const;
};

struct IsPalindrome
{
   bool operator ()( const std::string & ) const;
};

这是一个演示程序

#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>
#include <vector>
#include <algorithm>
struct IsPalindrome
{
    bool operator ()( const std::string &s ) const
    {
        std::string::size_type i = 0, j = s.length();
            do
            {    
                while ( i != j && !std::isalnum( s[i] ) ) ++i;
                while ( j != i && !std::isalnum( s[--j] ) );
            } while ( i != j && std::toupper( s[i] ) == std::toupper( s[j] ) && ++i );

//      unit test.:)    
//      std::cout << "i = " << i << ", j = " << j << std::endl;
        return ( i == j );
    }
};
int main() 
{
    std::vector<std::string> v =
    {
        "!bHvX!?!!vHbX",
        "A man, a plan, a canal: Panama",
        "race a car"
    };
    auto it = std::find_if( v.begin(), v.end(), IsPalindrome() );
    if ( it != v.end() )
    {
        std::cout << '"' << *it << "" is palindrome" << std::endl;
    }
    return 0;
}

输出为

"A man, a plan, a canal: Panama" is palindrome

至于您的代码,即使在函数的第一条语句中也存在错误。您忘记了以下循环中字符串的最后一个字符

    int i = 0, j = s.length() - 1;
    for (int k = 0; k < j; ++k)
        s[k] = tolower(s[k]);

您永远不会将最后一个字符转换为小写,因为循环条件是k<j和j是最后一个字符的索引。将循环更改为:

for (int k = 0; k <= j; ++k)
    s[k] = tolower(s[k]);

此外,如果使用字符常量(如'a')而不是ASCII代码,则代码将更易于阅读。

您可以在两个方向上遍历字符串,直到指针相遇。它将是这样的:

bool isPalindrome(std::string const& s) {
    int len = s.length();
    int i = 0;
    int j = len - 1;
    while (true) {
        // Skip garbage characters.
        while (i < len && !isalpha(s[i])) ++i;
        while (j >= 0  && !isalpha(s[j])) --j;
        if (i < j && tolower(s[i]) == tolower(s[j]))
            continue;
        if (i >= j)
            return true;
        return false;
    }

注意这里len是一个有符号的变量,尽管s.length()size_t

使用JavaScript

var isPalindrome = function (s) {
    let originalStringWithoutSplChr = s.replace(/[^a-zA-Z0-9]/g, "").toLowerCase()
    let newString = originalStringWithoutSplChr.split("").reverse().join("")
    if (newString === originalStringWithoutSplChr) {
         return true
    }
    else {
         return false
    }
};