1 暴力法
如字符串 hello
第1轮,新建一个空数组 []
h [h] 判断当前字符串长度和最大长度,大就赋值
he [h,e] 判断当前字符串长度和最大长度,大就赋值
hel [h,e,l] 判断当前字符串长度和最大长度,大就赋值
hell 数组中有l,退出,下一轮 。。。。
var lengthOfLongestSubstring1 = function (s) {
let r = 0;
if (s) {
let len = s.length;
let start = 0;
for (; start < len; start++) {
let cache = [];
for (let end = start; end < len; end++) {
if(!cache.includes(s[end])){ // 判断有没有这个字符,有就退出
cache.push(s[end])
if(cache.length > r) r = cache.length;
}else {
break;
}
}
}
}
return r;
}
2. 双指针
var lengthOfLongestSubstring = function (s) {
let len = s.length;
if (len < 2) return len;
let head = 0, cur = 1, res = 0;
while (cur < len) {
res = Math.max(res, cur - head);
let tmp = s.slice(head, cur);
let x = s.charAt(cur);
console.log(tmp, x)
if (tmp.includes(x)) {
let i = s.indexOf(x, head);
console.log(i);
head = i + 1;
}
cur++;
}
res = Math.max(res, cur - head);
return res;
}
3. 维护数组,遍历字符串
代码的思路比较简单,就是维护一个数组arr,对原字符串遍历,判断字符是否在arr里面,不在的话就直接push进去,再重新判断max的大小;在的话就将之前重复arr字符之前的项全部去除,再重新push进去。转载于LeetCode,原文链接 传送门
var lengthOfLongestSubstring = function(s) {
let arr = [];
let max = 0;
for(let item of s){
if(arr.includes(item)){
let index = arr.indexOf(item);
arr.splice(0, index + 1);
}
arr.push(item);
max = max > arr.length ? max : arr.length;
}
return max;
};
4. 滑动窗口
var lengthOfLongestSubstring = function(s) {
// 哈希集合,记录每个字符是否出现过
const occ = new Set();
const n = s.length;
// 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
let rk = -1, ans = 0;
for (let i = 0; i < n; ++i) {
if (i != 0) {
// 左指针向右移动一格,移除一个字符
occ.delete(s.charAt(i - 1));
}
while (rk + 1 < n && !occ.has(s.charAt(rk + 1))) {
// 不断地移动右指针
occ.add(s.charAt(rk + 1));
++rk;
}
// 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = Math.max(ans, rk - i + 1);
}
return ans;
};