文章本人首发于慕课网,原文链接:www.imooc.com/article/274…
leetCode有兴趣的可以去看看,我们直接上干货啦= =
第一道题 - 难度(★)
输入一个数组跟一个目标值,当数组中某两个数之和等于目标值,返回这两个数的索引(下标)注意这两个数不能相同。(如果内部有多对符合要求的输出一对即可)
var twoSum = function(nums, target) {
for(let i = 0; i < nums.length; i ++) {
for(let k = i + 1; k < nums.length; k ++) {
if(nums[k] + nums[i] === target) {
return [i,k];
}
}
}
};
复制代码
这个虽然简单,但是性能较差,能不能用O(n)的方式实现呢?怎么实现?
const handle = (nums, target) => {
let map;
for(let i = 0; i < nums.length; i ++) {
map = target - nums[i];
if(nums.indexOf(map) !== i && nums.includes(map)) {
return [i, nums.indexOf(map)]
}
}
}
var twoSum = function(nums, target) {
return handle(nums, target);
};
复制代码
这种方式呢,虽说看似只有一个for循环,但indexOf,includes方法都是比较耗时的,因而也不建议用。从下图中也可以看出,该方法较第一种我们认为比较慢的方法还整整慢了接近4倍。
const handle = (nums, target) => {
let map = {},
result = [];
for(let i = 0; i < nums.length; i ++) {
let firstNum = target - nums[i];
typeof map[firstNum] != "undefined" ? result.push(map[firstNum], i) : map[nums[i]] = i;
}
return result;
}
var twoSum = function(nums, target) {
return handle(nums, target);
};
复制代码
而此时所花的时间呢?72ms,大大的提升了效率,对吧?
这种通过对象的key来快速定位的情况在算法中应用很广泛,因为你可能就直接少了一个维度的循环,对象怎么快速找到这个key的,你不用管,反正,是基于底层实现,类似于数据库或者es,查索引的方式是无比快速的。远比你写一个for循环快。
嗯好了,第一道题铺得有点开,后面简单点。
第二道题 - 难度(★★)
找出一个字符串中最长不重复片段,返回这个片段的长度。
var lengthOfLongestSubstring = function(s) {
let map = {},
current = 0,
max = 0;
for(let i = 0; i < s.length; i ++) {
current = map[s[i]] >= current ? map[s[i]] + 1 : current;
map[s[i]] = i;
max = max > i - current + 1 ? max : i- current + 1;
}
return max;
}
复制代码
当然这里其实解法有很多种,但是这种方式是O(n)的方式,会比较快,性能较好。如果有更好的思路欢迎提出讨论。
第三题 - 难度(★★★)
输入两个数组,找出这两个数组所有数的中位数。注意时间复杂度应该为O(log(m + n))
const interchange = (arr, i, k) => [arr[i], arr[k]] = [arr[k], arr[i]];
const sort = (left, right, arr) => {
let i = left,
j = right,
reference = arr[left];
if(i >= j) return;
while(i < j) {
while(i < j && arr[j] >= reference) j --;
while(i < j && arr[i] <= reference) i ++;
arr[i] > arr[j] && interchange(arr, i, j);
}
interchange(arr, left, i);
sort(left, i - 1, arr);
sort(i + 1, right, arr);
}
var findMedianSortedArrays = function(nums1, nums2) {
let arr = nums1.concat(nums2),
len = arr.length;
sort(0, len - 1, arr);
return len%2 ? arr[Math.floor(len/2)] : (arr[len/2 - 1] + arr[len/2]) / 2;
};
复制代码
这里个人觉得这种方法还是比较慢,有什么更好的方式多谢指教。
第四题 - 难度(★★)
找出一个字符串中最长的回文字符串。
const palindromic = str => str.split("").reverse().join("") === str ? true : false;
const handle = s => {
let result = s[0];
for(let i = 0; i < s.length; i ++) {
if(s[i - 1] === s[i + 1]) {
let k = 2;
while(s[i - k] === s[i + k]) {
k ++;
}
result = result.length < (2 * k - 1) ? s.substr(i - (k - 1), 2 * k - 1) : result;
}
if(s[i] === s[i + 1]) {
let k = 1;
while(s[i - k] === s[i + 1 + k]) {
k ++;
}
result = result.length < 2 * k ? s.substr(i - (k - 1), 2 * k) : result;
}
}
return result;
}
var longestPalindrome = function(s) {
if(s === '' || s.length < 2 || palindromic(s)) return s;
return handle(s);
};
复制代码
这种方式应该算是较好的了,从结果上看的话,性能超过97.69%的同语言算法。