3.无重复字符的最长子串
给定一个字符串 s
,请你找出其中不含有重复字符的 最长 子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
提示:
s
由英文字母、数字、符号和空格组成
解法一(滑动窗口)
思路分析
- 首先确定是不含有重复字符子串而不是子序列;
- 对于如何计算最长子串长度,可以采用滑动窗口算法,从左到右依次遍历整个字符串;
- 使用变量
left
来表示最长子串的左边界(包含left指向的字符), 当指针i
遍历到某个字符s[i]
时; - 若
s[i]
出现过,即在区间[left, i-1]
中有重复字符, 则需要得到重复字符在无重复字符子串中的位置,假设为j
; - 则新得到的无重复子串区间为
[j+1, i]
, 此时新的子串长度为i - (j+1) + 1
, 即更新左边界left = j+1
; - 在遍历整个字符串的过程中, 会出现很多个新的子串长度, 即最大的子串长度也在其中;
- 同时在查找区间中是否有字符
s[i]
的重复字符时,可以采用哈希数据结构来降低查找的时间复杂度;
实现代码
java
class Solution {
// 滑动窗口
public int lengthOfLongestSubstring(String s) {
int n = s.length();
int ans = 0;
// 无重复字符串 左边界
int left = 0;
// 哈希表 记录对应字符所处位置索引
int[] hash = new int[129];
for (int i = 0; i < 129; i++) {
hash[i] = -1;
}
for (int i = 0; i < n; ++ i) {
// 获取当前字符
int ch = s.charAt(i);
// 保证窗口的左边界只会向右变化
left = Math.max(left, hash[ch]+1);
// 与新的子串长度进行比较, 筛选出最长子串
ans = Math.max(ans, i - start + 1);
// 更新字符的所处位置
hash[ch] = i;
}
return ans;
}
}
复杂度分析
- 时间复杂度:
- 空间复杂度: