LeetCode //回文子串 中心扩散法 //11.09

今天做几个回文子串题。

目前用两种方法:暴力法 和 中心扩散法(很适合回文题)

本文用到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

回文子串  

53864.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

最长回文子串  

210232.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也阔以

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值