今天做几个回文子串题。
目前用两种方法:暴力法 和 中心扩散法(很适合回文题)
本文用到js的一些方法:
toString():整数转化为字符串
slice(start,end),其中第一项是必须的,slice切片用于字符串和数组都可以
split(""),把字符串转化为数组,以引号中间为间隔,为空即把字符串一一分割开
reverse(),只能翻转数组,不能字符串,这也是为啥第一题用了这么多方法的原因
join(""),相当于split的逆方法,把数组转化为字符串,其余同理
1.
先做一个简单的,判断一个整数(或者字符串)是否回文,细节看注释:
var isPalindrome = function(x) {
// return JSON.stringify(x.toString().split("")) == JSON.stringify(x.toString().split("").reverse());
// 因为js里不能直接判断两个数组是否相等,直接判断会false
return x.toString().split("").join("") == x.toString().split("").reverse().join("");
// 或者再转化为字符串比较
// 还可以用for循环比较s[i] ?= s[n-i-1]
};
2.
647 | 538 | 64.5% | 中等 |
“给定一个string,你的任务是计算这个字符串中有多少个回文子串。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。”
示例 1:
输入:"abc"
输出:3
解释:三个回文子串: "a", "b", "c"
示例 2:
输入:"aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"
此题采用中心扩散法来做,额外写的函数是求从每一个中心位置能扩散的回文子串个数,由于中心处可以是1或2个长度(即回文数也是分为奇偶数),所以调用两次函数,再求和。
var countSubstrings = function(s) {
// 采用中心扩散法
var everyCount = function(l,r) {
let count = 0;
while(l >= 0 && r <= s.length-1 && s[l] == s[r]) {
l -= 1;
r += 1;
count += 1;
}
return count;
}
let ans = 0;
for(let i = 0; i < s.length; i++){
ans += everyCount(i,i);
}
for(let j = 0; j < s.length-1 ; j++) {
ans += everyCount(j,j+1)
};
return ans;
};
3.
5 | 2102 | 32.3% | 中等 |
“给定一个字符串 s
,找到 s
中最长的回文子串。你可以假设 s
的最大长度为 1000。”
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
注意,给定最大长度为1000,即最好不要用时间复杂度为n²以上的方法,可能会超时
①暴力法:
var longestPalindrome = function(s) {
let max_len = 1;
let res = s[0];
for(let i = 0; i < s.length - 1; i++) {
for(let j = i + 1; j < s.length; j++) {
if(j - i + 1 > max_len && s.slice(i,j+1) == s.slice(i,j+1).split('').reverse().join('')) {
max_len = j-i+1;
res = s.slice(i,j+1);
}
}
}
return res;
};
此法超时,只通过一半用例,
s.slice(i,j+1).split('').reverse().join('') 注意js里翻转字符串比较麻烦,reverse只能对数组用。
②中心扩散法:
在上一道题的基础上改进代码,但运行时间较长。
思路:把每个中心扩散的结果取最长的结果,并转化为数组,再放到一个新数组里(数组里有一对数组),然后找到子数组中长度最长的数组,再用join('')返回字符串
感觉有点复杂了 .......
var longestPalindrome = function(s) {
// 采用中心扩散法
let str = "";
var everyCount = function(l,r) {
while(l >= 0 && r <= s.length-1 && s[l] == s[r]) {
l -= 1;
r += 1;
}
str = s.slice(l+1,r);
//注意这里l要变成上一个l,所以加1 。push直接返回新数组
return str.split("");
}
// let ans = 0;
let arr = [];
for(let i = 0; i < s.length; i++){
arr.push(everyCount(i,i));
}
for(let j = 0; j < s.length-1 ; j++) {
arr.push(everyCount(j,j+1));
};
let most = [];
for(let m = 0; m < arr.length; m++) {
if(arr[m].length > most.length) {
most = arr[m];
}
}
return most.join("");
};
一开始在str = s.slice(l+1,r);这个地方有问题,因为没考虑l和r在循环之后又分别减加了1,
可以在chrome里进行调试:
ok,又复习了一下js的网页调试操作..
用node也阔以