题型:字符串、双指针
又是越界!!害我“鏖战”了将近一小时!
来源:LeetCode 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
题目描述(红字为笔者添加)
如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 (就是正反相同的字符串)。
字母和数字都属于字母数字字符。
给你一个字符串 s
,如果它是 回文串 ,返回 true
;否则,返回 false
。
题目样例
示例 1:
输入: s = "A man, a plan, a canal: Panama" 输出:true 解释:"amanaplanacanalpanama" 是回文串。
示例 2:
输入:s = "race a car" 输出:false 解释:"raceacar" 不是回文串。
示例 3:
输入:s = " " 输出:true 解释:在移除非字母数字字符之后,s 是一个空字符串 "" 。 由于空字符串正着反着读都一样,所以是回文串。
提示:
1 <= s.length <= 2 * 105
s
仅由可打印的 ASCII 字符组成
题目思路
这个题可以拆分为两块:①剔除非字母/数字字符 ②判断是否是回文串
其中判断回文串,笔者思路采用双指针——左右指针,有一个不同就可以return了
任务①这里,笔者有两个思路:Ⅰ.原地操作,在原数组上移动元素,优点是空间复杂度要低,缺点自然是其两次循环了。。 Ⅱ.创一个新字符串,让其表示纯【字母/数字】串,优点是时间复杂度低一点(因为少循环,代价是创了个字符串)
错误展示
贴一下思路Ⅰ的失败代码
class Solution {
public:
bool isPalindrome(string s) {
//要求:①保留字母和数字,②字母是转小写
int i,j,len=s.length();
int left=0,right;//左右指针
for(i=0;i<len;i++)
{
if(i<len-1 && !isalnum(s[i]))//如果是非数字/字母
{
for(j=i;j<len-1;j++)
{
s[j]=s[j+1];
}
i--;
len--;
}
}
if(isalnum(s[len-1])==0&&len>1)
{
i--;
//cout<<len<<endl;
len--;
}
//大写字母变小写
for(i=0;i<len;i++)
s[i]=tolower(s[i]);
right=len-1;
while(left<right)
{
if(s[left]!=s[right])
return 0;
else
{
left++;
right--;
}
}
return 1;
}
};
这个嵌套循环,感觉是“罪魁祸首”
C++代码
正片来了(创了个字符串来接盘)
class Solution {
public:
bool isPalindrome(string s) {
//要求:①保留字母和数字,②字母是转小写
int i,len=s.length();
int left=0,right;//左右指针
string temp_str="";
for(i=0;i<len;i++)
{
if(isalnum(s[i]))
{
// temp_str是空串,空串+=字符,相当于头插
temp_str+=s[i];
}
}
len=temp_str.length();
//大写字母变小写
for(i=0;i<len;i++)
temp_str[i]=tolower(temp_str[i]);
right=len-1;
while(left<right)
{
if(temp_str[left]!=temp_str[right])
return 0;
else
{
left++;
right--;
}
}
return 1;
}
};
结算页面
空间换时间