leetcode刷题笔记1-无重复字符的最长子串
一、无重复字符的最长子串(3)
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度
示例:
- 输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 - 输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。 - 输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。 - 输入: s = “”
输出: 0
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
二、思路分析
2.1 暴力法
- 思路:创建一个Hashset集合,将字符串中的字符依次放入Hashset集合,若集合长度增加,则加入的字符不重复,并比较该集合长度与最长子串的大小;反之,字符重复,清空集合元素。
- 代码:
public int lengthOfLongestSubstring(String s) {
int len=0;//最长子串的长度
int templen=0;//当前子串长度
int index=0;//索引
int setLen=0;//hashset的长度
//空字符串 特殊情况
if(s.length()==0){
return 0;
}
HashSet set=new HashSet();//创建Hashset集合
while(index<s.length()){
set.add(s.charAt(index));
setLen=set.size();
if(templen<setLen){
templen=setLen;
index++;
}else{//二者相等,说明重复了,index退回到字符子串开始的下一位
index=index-templen+1;
templen=0;//清零
set.clear();//集合清空
}
if(setLen>len){//更新最长子串长度
len=setLen;
}
}
return len;
}
- 评价:思路简单,但时间较长。
2.2 滑动窗口(最优)
-
思路:创建一个last[128]数组记录每个字符在字符串中出现的索引。需要两个指针,一个头指针(指向字符子串的头)和一个尾指针(指向字符子串的尾)。第二次出现该字符时,窗口需要在第一次出现的位置移动一位,确保不重复。
-
代码:
public int lengthOfLongestSubstring(String s) {
int[] last=new int[128];//保留字符出现的位置
for(int i=0;i<128;i++){
last[i]=-1;//初始化为-1
}
int start=0;//窗口开始位置
int res=0;//最长子串的长度
int n=s.length();//字符串长度
for(int i=0;i<n;i++){
int index=s.charAt(i);//字符在last中的下标
//第二次出现该字符时,窗口需要在第一次出现的位置移动一位。
start=Math.max(start,last[index]+1);
res=Math.max(res,i-start+1);//比较当前子串长度与最长子串长度
last[index]=i;//更新该字符在目标字符串的下标
}
return res;
}
- 评价:思路十分巧妙,以空间换时间,运行速度很快,只需2ms。