给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
关键字:哈希串、滑动窗口
自己的代码:
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.equals("")) return 0;
char[] chars = s.toCharArray();
int len = chars.length;
//res为当前已存在的无重复字符的字符串长度
int res = 1;
for(int i=0;i<len;i++){
Set set = new HashSet();
//判断界限
if(i+res>len)
break;
//将从当前位置i到长度为res的位置,所有字符添加到set
for (int k=i;k<i+res;k++)
set.add(chars[k]);
//如果set的长度和res不等,说明有重复字符,直接跳到下一位置i+1开始遍历
if(set.size()!=res)
continue;
//如果从i到i+res不存在重复字符,则继续往set添加字符
for(int j=i+res;j<len;j++){
//set添加字符成功,则将res加1,反正说明该字符已存在,则break,舍弃后面的字符
if(set.add(chars[j]))
res ++;
else
break;
}
}
return res;
}
}
官方代码:
public int lengthOfLongestSubstring(String s) {
Set set = new HashSet();
int n = s.length();
//双指针法,左指针为i,定义最左边的位置
//右指针初始化为-1,表示还未添加任何一个字符到set中
int res = 0,pre = -1;
for(int i=0;i<n;i++){
//除去第一个位置,后面遍历时都需要把最左侧的字符移除
if(i!=0)
set.remove(s.charAt(i-1));
//右指针遍历,如果当前字符未添加到set中,则进行添加,并且右指针向右移一位
while(pre + 1 <n && !set.contains(s.charAt(pre + 1))){
set.add(s.charAt(pre+1));
pre ++;
}
//两端指针的差值即为长度,取较大值
res = Math.max(res,pre-i+1);
}
return res;
}
思路
1)滑动窗口即为定义一个区域,随着遍历向右改变范围来进行判断;
2)本题要求最长的子串,如果从第i位到第j位为无重复子串,那么后续判断从第i+1位开始判断时,可以认定为从i+1到j直接无重复子串,即右侧从第j+1位开始遍历;
3)用set集合存储字符,来判断是否重复,遍历得到每次以i开始的最长子串,记录最大值返回。
优化:(用HashMap记录字符和出现的位置)
public int lengthOfLongestSubstring(String s) {
if (s.length() == 0) return 0;
//用map存储字符和出现的位置
Map<Character,Integer> map = new HashMap<>();
int res = 0;
//定义左侧的位置
int left = 0;
//遍历字符串,i表示当前位置,即右侧位置
for(int i=0;i<s.length();i++){
//如果当前字符已出现,更新左侧索引位置left为 该字符最后出现位置的下一位
if(map.containsKey(s.charAt(i))){
left = Math.max(left,map.get(s.charAt(i)) + 1);
}
//如果当前字符还未出现,存入集合中
map.put(s.charAt(i),i);
//取两端之间的长度,得到较大值
res = Math.max(res,i-left+1);
}
return res;
}
这种思路也是用了滑动窗口方法,亮点是用map存储了字符和它最后出现的位置,表面上看起来优化了一次循环,实际上map.containsKey()中也包含了循环查询,整体来说时空复杂度和上面的差不多。