前言:昨天过了个美好的 qi xi 节日,喝了点小酒,导致没完成,今天补回来补回来
题目:
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
-
解法一:(不推荐)
- 缺陷:1. 无法正确得到子串的数组 但是可以得到相同的长度 2. 遍历的更多次
- 时间复杂度:O(n)
- 空间复杂度:O(n)
//借助Math.Max方法得到最大值的方式。
// 1. 确定好数据结构 => 创建一个存储池 以及长度值为0
// 2. 确定好操作方式 => 开始遍历对比
var lengthOfLongestSubstring = function (s) {
let array = [],len = 0;
for(let i = 0; i< s.length; i++){ // n
if(array.indexOf(s[i]) === -1){
array.push(s[i]) // n - x
}else{
// 如果存在 则直接删除第一个
array.shift(); // n - x
i--; // n - x
continue; //不再对len赋值
}
len = Math.max(len,array.length) // n - y
}
return len
}
-
解法二:
- 减少了遍历次数
- 仍然没有得到正确的子串
var lengthOfLongestSubstring = function (s) {
let array = new Array();
let len = 0;
for (let i = 0; i < s.length; i++) {
// 存在即删除 (a)bca... 遇到有相同的之后 删除第一个然后以b开始为起点 以此类推 可得
if (array.indexOf(s[i]) > -1) {array.splice(0, array.indexOf(s[i]) + 1); continue}
array.push(s[i]);
len = Math.max(len, array.length);
}
return len
}
解法三:(推荐)
1. 指针解法:
var lengthOfLongestSubstring = function (s) {
// 定义滑动窗口左右指针 l,r 以及字符串长度 n 最终结果 max
let l = 0,
r = 0,
n = s.length,
max = 0,
// 定义 set 用来记录当前已经出现过的字符,用来作为是否重复出现过的依据
set = new Set()
// 约束窗口可滑动的范围:右指针不超过字符串长度,左指针不超过右指针
while (l <= r && r < n) {
// 如果当前字符未记录过:
// 1. 比较当前左右两指针间窗口大小和当前max大小,更新max
// 2. 记录当前字符到set中
// 3. 因为当前仍未发生重复,因此窗口可以继续扩大范围,右指针向右平移
if (!set.has(s[r])) {
max = Math.max(r - l + 1, max)
set.add(s[r])
r++
} else {
// 如果当前字符已经被记录过:
// 1. 右指针保持不动
// 2. 在set中移除左指针对应的字符 左指针右移缩小窗口大小
set.delete(s[l])
l++
}
}
return max
}