有效的回文OJ

时间:2014-10-25 08:40:47

标签: c++ string

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

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;
    }
};
Wrong answer:
Input:  "!bHvX!?!!vHbX" 
Output:   true 
Expected:  false

它有什么问题?

4 个答案:

答案 0 :(得分:1)

不要使用“魔术数字”。考虑到除了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]);

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

使用 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
    }
};