第一题 two sum
第二题 链表求和
第三题 找最长无重复字符的子串
str.charCodeAt(i);获取ascii码
这道题写起来比较简单,用一个ij维护的窗口向后移动,保持j总是增加,如果遇到相同字母,直接把i=相同字母的下标+1,最大长度为j-i中最大的。
第四题 给定两个分别排序好的数组,求中位数,算法思路不复杂,但是写起来条件复杂,不做解释了
第五题 求最长的回文子串
我们需要用到马拉车算法,首先马拉车采用的是从中间向两边扩展的回文判断法,遍历字符串每一个位置,然后向两边扩展,举个例子,假设我们在分析字符串 b a b d b a b ? ? ?. 假设已经遍历过了d,现在,我们知道位置4处的回文字符串长度为7,由于遍历过了前几个位置,那么我们也可以知道前几个的回文字符串的长度。现在我们来到了位置5,即b a b d b a b ? ? ?,那我们需不需要向两边扩展呢?答案是不需要,因为位置4是长度为7的回文字符串,那意味着,位置5和位置3应该是一样的,位置3的回文长度为1,位置5自然也为1,而且5没有在边界上,所以不需要再扩展。但考虑b a b d b a b ? ? ?。发现对称位置长度为3,此时新的回文字符串触及了已经扩展的边界,需要继续向外扩展。
总结算法为:
1,需要一个数组记录每个位置的回文字符串长度
2,记录已知回文最右边界,已经对应的中心
3,每次遍历的时候,分析中心是否在最右边界内,如果是,继续对称的位置的回文长度,如果长度到达右边界,需要继续扩展
4,为了方便,可以在字符之间插入#记号来去除对偶数回文和奇数回文的区别
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
if (s.length == 0)
return "";
// 预处理
var S = s.replace(/([a-zA-Z0-9])/g,'#$1') + '#';
var lengths = []; //记录对应位置的回文长度
var middle = -1; //记录最右边界的中心
var bound = -1; //记录最右边界
var max_length = -1;
var max_string;
//console.log(S)
for (var i = 0; i < S.length; i++) {
//取min是因为前面的回文可能会大于后面的回文的边界
lengths[i] = i < bound ? Math.min(lengths[2 * middle - i],bound-i):1;
//console.log(i,lengths[i]);
while (i + lengths[i] < S.length && i - lengths[i] > -1){
if (S[i + lengths[i]] == S[i - lengths[i]])
lengths[i]++;
else
break;
}
// 注意这里lengths[i]是比真实值大1的
// 要考虑更新middle和bound的问题
if (i + lengths[i] - 1 > bound) {
middle = i;
bound = i + lengths[i];
}
if(lengths[i] > max_length){
max_length = lengths[i];
max_string = S.substring(i - (lengths[i] - 1), i + lengths[i]);
}
}
return max_string.replace(/#/g,'');
};
说是很简单的,一打代码问题一堆,开心的写了几遍,竟然没有考虑输入为数字的情况,简直太丑恶了。