"Challenges are what make life interesting and overcoming them is what makes life meaningful." - Joshua J. Marine
1. 题目描述
2. 题目分析与解析
在解决这个问题之前我们先想一下普通的回文串是如何判断的。
-
方法1:通过将字符串反转,来判断两个字符串是否相等。
-
方法2:双指针,一个从前向后,一个从后向前,判断字符是否相等。
而现在的题目只是在判断普通回文串的基础上加上了一些无关紧要的字符,那我们是不是就可以将该问题分解成:
-
将无关紧要的字符去掉(对应reverse原始字符串的方法),或者不考虑他(对应双指针方法)
-
在判断是否为回文串
因此有了上述思路就可以写代码了。
3. 代码实现
// 双指针方法
public boolean isPalindrome(String s) {
// 解题思路
// 1. 大写字符转换为小写字符、并移除所有非字母数字字符(但无需真正移除,只需要在遍历时如果非字母就略过)
// 2. 双指针判断是否为回文串
// 3. 时间复杂度O(n)
// 4. 空间复杂度O(1)
// 5. 代码实现
// 1. 大写字符转换为小写字符
String lowerCase = s.toLowerCase();
// 2. 双指针判断是否为回文串
int left = 0;
int right = s.length() - 1;
while (left < right) {
// 2.1. 如果不是字母数字字符,跳过
if (!Character.isLetterOrDigit(lowerCase.charAt(left))) {
left++;
continue;
}
if (!Character.isLetterOrDigit(lowerCase.charAt(right))) {
right--;
continue;
}
// 2.2. 如果不相等,返回false
if (lowerCase.charAt(left) != lowerCase.charAt(right)) {
return false;
}
// 2.3. 移动指针
left++;
right--;
}
return true;
}
// 反转字符串
public boolean isPalindrome2(String s) {
StringBuffer clearStr = new StringBuffer();
int length = s.length();
for (int i = 0; i < length; i++) {
char ch = s.charAt(i);
// 删除无关紧要的字符
if (Character.isLetterOrDigit(ch)) {
clearStr.append(Character.toLowerCase(ch));
}
}
// 反转字符串
StringBuffer sgood_rev = new StringBuffer(clearStr).reverse();
// 判断是否为回文串
return clearStr.toString().equals(sgood_rev.toString());
}
代码相关注释已经比较清晰的解释了不在赘述。
4. 运行结果
5. 相关复杂度分析
1. 反转字符串
-
时间复杂度:O(n),其中 n 是字符串 s 的长度。
-
空间复杂度:O(n)。由于我们需要将所有的字母和数字字符存放在另一个字符串中,在最坏情况下,新的字符串与原字符串 s 完全相同,因此需要使用 O(n) 的空间。
2. 双指针
-
时间复杂度:O(n),其中 n 是字符串 s 的长度。
-
空间复杂度:O(1)。
顺便推广一下个人公众号: