内容简介:题目:暴力解决,用
题目:
Example 1:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
Example 2:
Input: "cbbd"
Output: "bb"
即求最长回文子序列
原题链接: https://leetcode.com/problems...
此篇博客仅为学习记录
我的解法及代码
暴力解决,用 outP 及 innerP 进行两层遍历: outP 循环中套一层for循环,用 innerP 遍历,求最长回文序列字符串,同时用 logest 变量记录最长子序列
这种写法很 暴力 , 效率很低 ,outP一层循环,innerP一层循环,回文序列对比一层,时间复杂度为n^3
辣鸡代码
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
let strL = s.length,
longest = 0,
resultS = '';
for(let outP = 0; outP < strL; outP ++){
for(let innerP = outP + longest; innerP < strL; innerP++){
let tempS = s.slice(outP, innerP + 1),
tempSL = tempS.length,
halfL = parseInt(tempSL/2),
sub1 = null,
sub2 = tempS.slice(halfL, tempSL);
if(tempSL % 2 === 0){
sub1 = tempS.slice(0, halfL)
}else{
sub1 = tempS.slice(0, halfL + 1)
}
// console.log('halfL:' + halfL);
// console.log('tempS:' + tempS);
// console.log('sub1:' + sub1);
// console.log('sub2:' + sub2);
// console.log('------------------')
if(compareReverse(sub1, sub2)){
longest = tempSL;
resultS = tempS;
}
}
}
return resultS;
};
function compareReverse(s1, s2){
let length = s1.length,
half = Math.ceil(length),
flag = true;
for(let i = 0; i < half; i++){
if( !(s1[i] === s2[length-1-i])){
flag = false;
break;
}
}
return flag;
}
学习高效的解法
主要学习了两种,一种是常规的中心检测法,时间复杂度为n^2,一种是Manacher's Algorithm 马拉车算法,时间复杂度为n。
这里主要学习高效的马拉车写法
学习及参考链接在此: 最长回文子串——Manacher 算法
中心检测法缺点
1.对奇数字符串与偶数字符串需要进行处理
奇偶数会为处理带来一些麻烦,但是对算法的效率影响不大
2.子串重复访问
例如 babad 字符串:
str: a b c b a b a index: 0 1 2 3 4 5 6
使用中心检测法,当index = 2时,访问了 abcba ,当index = 3时,访问了 cba , abcba 后半串的 cba 又被访问了一次
解决方法
1.针对奇偶问题
在字符串中插入'#'(当然其他字符也可以),这样无论是奇数还是偶数,所有的字符串长度都会变为奇数
例子1:abc -> #a#b#c# 例子2:abcd -> #a#b#c#d#
2.针对重复的问题
核心思想:利用以计算的回文子串长度再进行扩充。
此篇博文写得很好易懂,推荐: 最长回文子串——Manacher 算法
新写的代码
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
let s2 = getS2(s),
R = getR(s2),
maxRight = 0, //记录最右边界
pos = 0, //记录最右边界时对应的中心位置
maxIndex = 0; //记录最长回文串对应的下标
s2.forEach((e, i)=>{
if(i < maxRight){ //在MR左边
const j = 2 * pos - i;
R[i] = Math.min(maxRight - i, R[j]);//保证回文的情况下,包裹于已探索区域内
let lp = i - R[i],
rp = i + R[i];
while(s2[lp] === s2[rp] && lp >= 0 && rp < s2.length){
lp--;
rp++;
R[i]++;
}
if(rp > maxRight){
pos = i;
}
}else{//在MR右边,包括同MR同一个位置
let lp = i - 1,
rp = i + 1;
while(s2[lp] === s2[rp] && lp >=0 && rp < s2.length){
lp--;
rp++;
R[i]++;
}
pos = i;
maxRight = rp;
}
maxIndex = R[i] > R[maxIndex]? i:maxIndex;
});
let subArray = s2.slice(maxIndex - R[maxIndex] + 1, maxIndex + R[maxIndex]),
result = '';
for(let item of subArray){
if(item !== '#'){
result += item
}
}
// console.log(result);
return result;
};
function getS2(s){//获得插入'#'后的字符串
const sLength = s.length,
s2Length = 2 * sLength + 1;
let s2 = new Array(s2Length).fill('#');
for(let j = 1, i = 0; j < s2Length; j=j+2, i++){
s2[j] = s[i];
}
return s2;
}
function getR(s2){//创建回文字符串半径数组
let R = new Array(s2.length).fill(1);//初始值为1;
return R;
}
结果
仅仅超过60%,沉默.jpg,还有很多地方可以优化
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- LeetCode——Longest Palindromic Substring
- leetCode 系列 (5) Longest Palindromic Substring
- Leetcode基础刷题之PHP解析(5. Longest Palindromic Substring )
- leetcode刷题心得 005: Longest Palindromic Substring (最长回文字符串)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First Design Patterns
Elisabeth Freeman、Eric Freeman、Bert Bates、Kathy Sierra、Elisabeth Robson / O'Reilly Media / 2004-11-1 / USD 49.99
You're not alone. At any given moment, somewhere in the world someone struggles with the same software design problems you have. You know you don't want to reinvent the wheel (or worse, a flat tire),......一起来看看 《Head First Design Patterns》 这本书的介绍吧!