一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
前言
每日一题,轻松解题
每日一题为刷题系列 每日刷一题LeetCode题,并且对题目进行分析,分享思路。
正文
:不含重复字符的最长子字符串
难度:中等
题目要求:
给定一个字符串 s ,请你找出其中不含有重复字符的 最长连续子字符串 的长度。
细节:这里说的是连续子字符串,而不是子序列,必须要是连续的不重复的。
举个例子
输入: a = abcddddddde
输出: 4
解释: 不含有重复字符的最长连续子字符串abcd。
:解题
方法一 :
理清思路:滑动窗口 + hashMap
滑动窗口算法思想是非常重要的一种思想,可以用来解决数组,字符串的子元素问题。它可以将嵌套循环的问题,转换为单层循环问题,降低时间复杂度,提高效率。
滑动窗口的思想非常简单,它将子数组(子字符串)理解成一个滑动的窗口,然后将这个窗口在数组上滑动,在窗口滑动的过程中,左边会出一个元素,右边会进一个元素,然后只需要计算当前窗口内的元素值即可。
可用滑动窗口思想解决的问题,一般有如下特点:
- 窗口内元素是连续的。就是说,抽象出来的这个可滑动的窗口,在原数组或字符串上是连续的。
- 窗口只能由左向右滑动,不能逆过来滑动。就是说,窗口的左右边界,只能从左到右增加,不能减少,即使局部也不可以。
算法思路
1、使用双指针中的左右指针技巧,初始化 left = right = 0,把索引闭区间 [left, right] 称为一个「窗口」。
2、先不断地增加 right 指针扩大窗口 [left, right],直到窗口符合要求。
3、停止增加 right,转而不断增加 left 指针缩小窗口 [left, right],直到窗口中的字符串不再符合要求。同时,每次增加 left,我们都要更新一轮结果。
4、重复第 2 和第 3 步,直到 right 到达尽头。
编辑代码:
var findAnagrams = function(s, p) {
const m = s.length,
n = p.length,
letterArr = [],
res = []; //收集起始索引的结果
if(n > m){
return res;
}
// 初始化26个英文字母的字符数,为0
for(let i = 0;i <= 26;i++){
letterArr.push(0);
}
// 收集p字符串的字符
for(let j = 0;j < n;j++){
letterArr[p[j].charCodeAt() - "a".charCodeAt()]--;
}
// 定义开始指针
let left = 0;
for(let right = 0;right < m;right++){
const x = s[right].charCodeAt() - "a".charCodeAt();
letterArr[x]++;
while(letterArr[x] > 0){
letterArr[s[left].charCodeAt() - "a".charCodeAt()]--;
left++;
}
if(right - left + 1 === n){
//此时left就是满足条件的起始索引
res.push(left);
}
}
return res;
};
总结
无论做什么分析最重要,其中我们分析了题目,分析了解题思路,其实在分析完解题思路后,代码其实就是很简单的事情了,养成习惯,无论做什么之前,都要进行分析,这样有助于你更快更好的完成这件事。