Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.
For example,
"A man, a plan, a canal: Panama"
is a palindrome.
"race a car"
is not a palindrome.
题意是判断回文,很简单的一道题,只要一个一个字节判断就好了,不过做这道题碰到了一些有意思的事情,所以记一下。
首先我用了个最简单粗暴的办法,拿一个新的string装好所有s中的palindrome并且转换为小写。
不考虑时间空间,a了再说。
bool isPalindrome(string s) {
string tmp;
for (auto &c : s)
{
c = tolower(c);
if (c >= 'a' && c <= 'z' ||( c>='0' && c <= '9'))
tmp.push_back(c);
}
auto i = tmp.cbegin();
auto j = tmp.crbegin();
if (!tmp.size())
return true;
while (&*i < &*j)
{
if (*i != *j)
return false;
++i;
++j;
}
return true;
}
居然过了,但是要了20多的ms排名很靠后,而且消耗了多余的空间。
稍微改进一下
bool isAlphanumeric(char c)
{
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9');
}
bool isPalindrome2(string s)
{
if (!s.size())
return true;
auto i = s.begin();
auto j = s.rbegin();
bool judge = false;
while (&*i < &*j)
{
if (!(('a' <= *i && *i <= 'z') || ('A' <= *i && *i <= 'Z') || ('0' <= *i && *i <= '9')))//(!isAlphanumeric(*i))
{
i++;
judge = false;
}
else
judge = true;
if ((!(('a' <= *j && *j <= 'z') || ('A' <= *j && *j <= 'Z') || ('0' <= *j && *j <= '9'))))//(!isAlphanumeric(*j))
{
j++;
judge = false;
}
else
judge = judge && true;
if (judge)
{
if(tolower(*i) != tolower(*j))//if (*i != *j && abs(*i - *j) != 32)
return false;
i++;
j++;
}
}
return true;
}
比刚才好一点,18ms。
这里有个很奇怪的事情,我以为把函数isAlphanumeric中的内容直接写到if的判断中去会提供运行效率,但是oj给出的结果竟然多了1ms,即如果使用注释的代码时间只要17ms。
调用函数不是应该会消耗时间么,即使编译器优化才用内联消耗的时间也应该是一样的啊。不太清楚怎么回事,想明白了再更新吧。
leetcode上最快的能达到14ms,我觉得他们应该没有用到迭代器而是直接操作下标了。最后改了一下,果然达到了。
bool isPalindrome3(string s)
{
int i = 0;
int j = s.size() -1 ;
while (j>i)
{
while (!isAlphanumeric(s[i]) && i < j)
i++;
while (!isAlphanumeric(s[j]) && i < j)
j--;
if (j > i)
{
if (s[i] != s[j] && abs(s[i] - s[j]) != 32)
return false;
i++;
j--;
}
}
return true;
}
这里还有个一个有意思的事情,我试过把i与j的类型用size()的返回值定义,发现在比较j>i时,j=-1竟然比i=0要大。原来size的返回值是一个64位的无符号数,应该是把-1当成了2^64-1了,即使j的类型为int也会有这种效果。