Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一.题目
3. 无重复字符的最长子串 给定一个字符串
s,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104s由英文字母、数字、符号和空格组成
二、思路分析:
首先看到题目,对于字符串进行相关操作,可以想到利用滑动窗口思路进行求解问题,这道题是需要找出不含有重复字符的最长子串的长度,所以我们需要对滑动窗口的结构进行修改。
第一种常规滑动窗口思路求解:左右指针初始化,右指针右移一直循环直到字符串的最右端,如果滑动窗口中有字符c,则直接将window中该字符加一,如果没有将字符存入window中,存入数值后判断该字符的数值是否大于1,如果大于1则不符合无重复字符的子串的规定,就需要对滑动窗口进行缩小操作直到该字符只出现一次,达到符合最小子串的要求需要对结果res进行一次更新保证是最长子串。
第二种方法是对滑动窗口的另一种理解:对字符串进行循环,利用indexOf判断循环中的字符是否在待定字符串oString中,如果indexOf值为-1直接添加,如果不是需要把先前的重复字符以及他左边的全部剔除,每次走完这一步就需要对结果result进行更新操作。
三、代码:
第一种:
var lengthOfLongestSubstring = function(s) {
//左右指针、结果、滑动窗口初始化
let left = right = 0
let window = {}
let res = 0
while(right < s.length){
let c = s[right]
right++
//如果滑动窗口中有字符c,则直接计数即可,如果没有将字符存入window中
window[c] = (window[c] || 0) + 1
//如果存在特定字符超过1的时候进行缩小滑动窗口操作
while(window[c]>1){
let d = s[left]
window[d]--
left++
}
//直接进行res更新
res = Math.max(res,right-left)
}
return res
}
第二种:
var lengthOfLongestSubstring = function(s) {
let len = s.length;
if(len == 0)return 0;
let oString = '';
let result = 0;
//既然最终结果是长度,我们只需要求出长度最大即可
for(let i=0;i<len;i++){
let flag = oString.indexOf(s[i]);
if(flag == -1){
oString +=s[i];
}else{
//子串里面存在相同字符,则去掉该字符以及左边的
oString +=s[i];
oString = oString.substring(flag+1,oString.length);
}
result=result>oString.length?result:oString.length;
}
return result;
};
四、总结:
这是字符串相关问题的第四题,也是利用滑动窗口思路求解问题的第四题,再这些题目中不断地利用滑动窗口框架已经能够让我熟练掌握解决字符串问题了,希望自己还能够不断地进步,继续练习!