回文串相关的题

求最长回文串

题目

题目链接
给你一个字符串 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暂存回文串的边界(开区间)

  1. 核心代码模式
/**
 * @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)
};
  1. 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

题解

  1. 方法一:将数字转换成字符串,然后转成数组再反转再转换回字符串
/**
 * @param {number} x
 * @return {boolean}
 */
var isPalindrome = function(x) {
    return String(x)==String(x).split('').reverse().join('')
};

image.png

  1. 方法二:已知负数不可能是回文数,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('')
};

image.png

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值