剑指 Offer 48. 最长不含重复字符的子字符串
Posted RainsX
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 48. 最长不含重复字符的子字符串相关的知识,希望对你有一定的参考价值。
剑指 Offer 48. 最长不含重复字符的子字符串
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
提示:
- s.length <= 40000
方法一:动态规划 + 哈希表
- Java 的 getOrDefault(key, default) , 代表当哈希表包含键 key 时返回对应 value ,不包含时返回默认值 default。
- tmp<j-i时候,tmp+1,即dp[j]=dp[j-1]+1
- tmp>=j-i时候,j-i,即dp[j]=j-i
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> dic = new HashMap<>();
int res = 0, tmp = 0;
for(int j = 0; j < s.length(); j++) {
int i = dic.getOrDefault(s.charAt(j), -1); // 获取索引 i
dic.put(s.charAt(j), j); // 更新哈希表
tmp = tmp < j - i ? tmp + 1 : j - i; // dp[j - 1] -> dp[j]
res = Math.max(res, tmp); // max(dp[j - 1], dp[j])
}
return res;
}
}
方法二:双指针 + 哈希表
做题思路:
循环索引j遍历字符s,然后如果查找到重复数则更新左指针i,否则继续记录哈希表,更新res结果,最后再返回res即可
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;
}
}
除了这两个之外,k神还有一个方法。
方法三: 动态规划 + 线性遍历
与方法一、二的代码有点类似,除了在while那里为了实现线性查找有点变化。
- 左边界 ii 获取方式: 遍历到 s[j]s[j] 时,初始化索引 i = j - 1i=j−1 ,向左遍历搜索第一个满足 s[i] = s[j]s[i]=s[j] 的字符即可 。
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> dic = new HashMap<>();
int res = 0, tmp = 0;
for(int j = 0; j < s.length(); j++) {
int i = j - 1;
while(i >= 0 && s.charAt(i) != s.charAt(j)) i--; // 线性查找 i
tmp = tmp < j - i ? tmp + 1 : j - i; // dp[j - 1] -> dp[j]
res = Math.max(res, tmp); // max(dp[j - 1], dp[j])
}
return res;
}
}
参考链接:
以上是关于剑指 Offer 48. 最长不含重复字符的子字符串的主要内容,如果未能解决你的问题,请参考以下文章