目录
最长不含重复字符的子字符串
描述
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例 1
输入
"abcabcbb"
输出
3
解释
因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2
输入
"bbbbb"
输出
1
解释
因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3
输入
"pwwkew"
输出
3
解释
因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
提示
s.length <= 40000
方法一:迭代
直接暴力求解,从每个元素开始查找不重复的最长子串长度,
class Solution {
public int lengthOfLongestSubstring(String s) {
if ("".equals(s)) return 0;
Set<String> set=new HashSet<>();//创建哈希表,用于计算不同字符
String[] strArr = s.split("");
int len=0,maxlen=0;
for (int i = 0; i < strArr.length; i++) {
set.add(strArr[i]);
len++;
for (int j = i+1; j < strArr.length; j++) {
if (set.contains(strArr[j])){
set.clear();
if (maxlen<len){
maxlen=len;
}
len=0;
break;
}else{
set.add(strArr[j]);
len++;
}
}
if (len>maxlen){
maxlen=len;
}
len=0;
}
if (len>maxlen) maxlen=len;
return maxlen;
}
}
方法二:动态规划+哈希表
我们定义dp[j]代表以字符s[j]结尾的最长不重复子串的长度,我们假设字符s[j]左边距离最近的相同字符为s[i],即s[i]=s[j],那么就可以得到状态转移方程:
- 当i<0时,那么s[j]左边没有相同的字符,则dp[j]=dp[j-1]+1
- 当dp[j-1]<j-i时,说明字符s[i]在dp[j-1]的最长子串之外,则dp[j]=dp[j-1]+1
- 当dp[j-1]>=j-i时,说明字符s[i]在dp[j-1]的最长子串内部,则dp[j]=j-i
我们可以将1,2两种情况合并,最近的相同字符出现的位置我们可以用哈希表来存储。
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> dic = new HashMap<>();//存储字符出现的最近下标
int tempDp = 0, res = 0;
for (int i = 0; i < s.length(); i++) {
int index = dic.getOrDefault(s.charAt(i), -1);//找到则返回下标,没找到则返回-1
dic.put(s.charAt(i), i);//更新当前字符出现的最近下标
tempDp = tempDp < i - index ? tempDp + 1 : i - index;//更新当前字符结尾的最长字串长度
res = Math.max(res, tempDp);//更新最长长度
}
return res;
}
}
方法三:双指针+哈希表
本方法和方法二类似,不同点在于左边界的定义。
同样的哈希表还是用来统计字符s[j]最近出现的索引,
然后我们会根据上一轮的左指针i和字符s[j]最近出现的下标dic[s[j]],更新左边界i,保证区间[i+1,j]之间没有重复字符串且最大
接着更新最大长度res,取上一轮res和本轮双指针[i+1,j]的区间长度的最大值
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> dic = new HashMap<>();
int i = -1, res = 0;
for(int j = 0; j < s.length(); j++) {
if(dic.containsKey(s.charAt(j)))
i = Math.max(i, dic.get(s.charAt(j))); // 更新左指针 i
dic.put(s.charAt(j), j); // 哈希表记录
res = Math.max(res, j - i); // 更新结果
}
return res;
}
}