求最长回文串
题目
题目链接
给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成
题解
中心扩散法
思路:由回文串的特点可知回文串关于中心两边相等。寻找回文串的中心,然后向两端扩展,直到两端不等。因为不能确定回文串的中心在哪,所以需要从字符串的[0,length-1]位循环假设回文串中心,因为每次循环并不知道回文串长度是奇数还是偶数,所以helper(i,i)
和helper(i,i+1)
都要执行。这里设置了双指针l, r暂存回文串的边界(开区间)
- 核心代码模式
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
// 如果字符串只有一个字符或是空串就返回其本身
if(s.length<=1){
return s
}
// l, r记录当前回文串的边界(开区间)
let l=0
let r=0
// m,n是回文串扩展起始位(中心),函数helper以m,n开始向两端扩展求最大回文串
function helper(m,n){
// while循环找出回文串边界m,n(开区间)
while(m>=0&&n<s.length&&s[m]==s[n]){
m--;
n++;
}
// 跳出循环后,m,n为本轮i循环找到的边界值(开区间)
// n-m-1是回文串的长度
if(n-m-1>r-l-1){
// 更新l, r所记录的当前回文串的边界
l=m
r=n
}
}
// 因为不知道回文串的中心在哪,所以字符串的所有位置都要试一遍
for(let i=0;i<s.length;i++){
// 因为不知道回文串长度是奇数还是偶数,所以每次循环对于奇数的helper和对于偶数的helper都要执行一遍
// 若回文串长度是奇数
helper(i,i)
// 若回文串长度是偶数
helper(i,i+1)
}
// 注意slice的下限是闭区间,上限是开区间,所以实际截取的范围是[l+1,r-1]
return s.slice(l+1,r)
};
- ACM
// readline()读入一行的输入,注意读入的是字符串
let s = readline();
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
// 如果字符串只有一个字符或是空串就返回其本身
if(s.length<=1){
return s
}
// l, r记录当前回文串的边界(开区间)
let l=0
let r=0
// m,n是回文串扩展起始位(中心),函数helper以m,n开始向两端扩展求最大回文串
function helper(m,n){
// while循环找出回文串边界m,n(开区间)
while(m>=0&&n<s.length&&s[m]==s[n]){
m--;
n++;
}
// 跳出循环后,m,n为本轮i循环找到的边界值(开区间)
// n-m-1是回文串的长度
if(n-m-1>r-l-1){
// 更新l, r所记录的当前回文串的边界
l=m
r=n
}
}
// 因为不知道回文串的中心在哪,所以字符串的所有位置都要试一遍
for(let i=0;i<s.length;i++){
// 因为不知道回文串长度是奇数还是偶数,所以每次循环对于奇数的helper和对于偶数的helper都要执行一遍
// 若回文串长度是奇数
helper(i,i)
// 若回文串长度是偶数
helper(i,i+1)
}
// 注意slice的下限是闭区间,上限是开区间,所以实际截取的范围是[l+1,r-1]
return s.slice(l+1,r)
};
求回文串个数
题目
题目链接
给定一个字符串 s ,请计算这个字符串中有多少个回文子字符串。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
示例 1:
输入:s = “abc”
输出:3
解释:三个回文子串: “a”, “b”, “c”
示例 2:
输入:s = “aaa”
输出:6
解释:6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”
提示:
1 <= s.length <= 1000
s 由小写英文字母组成
题解
思路:字符串s的每个位置都假设一遍是中心,求以当前位置为中心的最大奇数长和偶数长的回文串。然后再统计相应中心位置的最大回文串包含的子回文串个数,这样累加就是总回文串个数
/**
* @param {string} s
* @return {number}
*/
var countSubstrings = function(s) {
// 首先字符串s的每一个单独的字符是一个回文串,单独的字符个数就等于字符串长度
let count=s.length;
// m,n是回文串扩展起始位(中心),函数helper以m,n开始向两端扩展求最大回文串
function helper(m,n){
// while循环找出回文串边界m,n(开区间)
while(m>=0&&n<s.length&&s[m]==s[n]){
m--;
n++;
}
// 跳出循环后,m,n为本轮i循环找到的边界值(开区间)
// n-m-1是回文串的长度
// 求出不同中心位置的最大回文串s[m+1,n-1]后,再计算该回文串可分解为多少个子回文串(单独一个的字符除外,因为已经计算过了)。个数为长度一半的整数
count+=parseInt((n-m-1)/2)
}
// 字符串的每个位置都假设一遍是中心,求以当前位置为中心的最大奇数长和偶数长的回文串。
for(let i=0;i<s.length;i++){
// 求以当前i为中心的最大奇数长回文串
helper(i,i)
// 求以当前i为中心的最大偶数长回文串
helper(i,i+1)
}
return count
};
判断是否为回文数
题目
题目链接
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121 是回文,而 123 不是。
示例 1:
输入:x = 121
输出:true
示例 2:
输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。
提示:-231 <= x <= 231 - 1
题解
- 方法一:将数字转换成字符串,然后转成数组再反转再转换回字符串
/**
* @param {number} x
* @return {boolean}
*/
var isPalindrome = function(x) {
return String(x)==String(x).split('').reverse().join('')
};
- 方法二:已知负数不可能是回文数,0是回文数
加上判断内存耗费得少一些,但时间也慢了些
/**
* @param {number} x
* @return {boolean}
*/
var isPalindrome = function(x) {
if(x<0) return false
if(x==0) return true
return String(x)==String(x).split('').reverse().join('')
};