给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:
输入: "A man, a plan, a canal: Panama"
输出: true
示例 2:
输入: "race a car"
输出: false
这个题我一直没有弄明白,我去百度了什么是回文串,得到的答案都是像 abba 这样的,但我看官网给的例子发现并不是这样的,所以我需要对题目进行说明,也就是当去除非数字和字母以后,抛开大小写的时候,满足从前到后或从后到前都一样的字符串是回文串。
我按正常思路实现,也就是先对字符串进行处理然后再判定是不是回文串,其实可以直接操作,使用双指针很容易验证。我的算法实现为:
/**
* @param {string} s
* @return {boolean}
*/
var isPalindrome = function (s) {
const c0 = "0".charCodeAt(0);
const c9 = "9".charCodeAt(0);
const cA = "a".charCodeAt(0);
const cZ = "z".charCodeAt(0);
// 先处理传进来的字符串,也就是删除非字母数字
const str = [];
for(let i = 0; i < s.length; i ++) {
const c = s.charAt(i).toLocaleLowerCase().charCodeAt(0);
if ((c >= c0 && c <= c9) || (c >= cA && c <= cZ) ) {
str.push(c)
}
}
// 验证是不是回文串
for (let m = 0, n = str.length - 1; m < n; m ++, n --) {
if (str[m] !== str[n]) {
return false;
}
}
return true;
};
预处理就是处理掉非要求的字符,我这里就是将字符串里面的字符转换成 charCode ,这样方便直接进行比较。每个字符所对应的 charCode 在 ACSII 表上有,我偷一个懒,使用 charCodeAt 函数拿。
接下来我来分析我算法的时间复杂度和空间复杂度,以前都没有分析,今天看了时间复杂度和空间复杂度怎么分析的文章,于是我就开始尝试。
时间复杂度:
两个 for 循环,而 for 循环都是依赖于传进来的字符串的长度,长度是未知的,假设为 n,也就是 for 遍历的次数取决于传进来的字符串的长度,第一个 for 循环的 i 从 0->n 也就是 O(n) , 第二个 for 循环从 m->n/2 也就是 O(n) , 对于这种去掉常数部分,可以得到 O(n) ,之所以去掉主要是因为当 n->∞ 得到的值也是无穷大的,对于这种并列的应该取最大值,也就是 O(n) 所以时间复杂度也就是 O(n) ,当然小的我还没有算,比如前面的 const c0 = "0".charCodeAt(0); 这样的语句时间复杂度是 O(1) ,明显小于后面的 for 循环,所以直接不说了。
空间复杂度:
其中 c0,c9,cA,cZ 这些的空间复杂度为 O(1) , str 数组的长度取决于传入字符串 s 的长度,虽然有时候会小,但要考虑的是最坏的情况,或者是最普遍的情况。 所以 str 数组的空间复杂度为: O(n) 。总体下来这个函数的空间复杂度为: O(n) 。
综上所述,我这个算法题的时间复杂度和空间复杂度都是 O(n) 。
来源:力扣(LeetCode)