题目描述:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
一般这种寻找连续的字符串之类的题都是滑动窗口或者动态规划的解法,这题我用的滑动窗口。
想象一下,字符串是长长的一排,现在有一个不定长的窗口去框住最长的不重复字符串,
分步来看【举例来说,abcabcda】:
窗口从头开始,窗口长为零,窗口内没有重复符号,窗口就像右拓展一位【[]abcabcda --> [a]bcabcda】
一直向右拓展,检测到即将添加的符号在窗口内出现过,就将窗口的左端向右收缩【[abc]abcda --> a[bc]abcda】
这样只要有一个char[] let数组记录窗口内出现过的字符,还有cur变量当前窗口内个数,以及res变量纪录最大值。
反思错误:
①没有注意到是所有字符,以为只有小写字母,所以char[]数组大小设置为26。【常用ascll码最大值为127,应设置长度128】
②居然让窗口没有右滑,无限循环了。
Java代码:
class Solution {
public int lengthOfLongestSubstring(String s) {
// if(s==null || s.equals(""))return 0;//我上来就写上了,其实不需要。
int[] let = new int[128];//因为ascll码0~127
int l=0,r=0;//窗口的左右端
int res = 0;//结果
char[] cs = s.toCharArray();
int len = cs.length;//字符串长度
int cur = 0;//记录窗口内字符个数
//滑动窗口具体实现,l,r不能越界
while(r<len && l<=r){
//let==0:窗口内没有当前字符
if(let[cs[r]] == 0){
let[cs[r]] = 1;//将当前字符纳入窗口内
++r;//窗口右扩
++cur;//窗口内字符数加一
res = res>cur?res:cur;//纪录最大值
}
//let==1:窗口内有当前字符
else{
//只要当前字符在窗口内存在,就循环缩小左端,直至let==0
while(let[cs[r]]!=0 && l<r){
let[cs[l]] = 0;//缩小左端代表:左端该值退出窗口
++l;//左端右移
--cur;//窗口内字符数减一
}
}
}
return res;
}
}
运行结果:
执行用时 :6 ms, 在所有 Java 提交中击败了98.84%的用户
内存消耗 :38 MB, 在所有 Java 提交中击败了90.19%的用户