题目
3. 无重复字符的最长子串
难度中等7441收藏分享切换为英文接收动态反馈
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列, 不是子串。
提示:
0 <= s.length <= 5 * 104s由英文字母、数字、符号和空格组成
解法1:
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length() == 0) {
return 0;
}
int result = 1;
int index = 1;
HashSet<Character> set = new HashSet<>();
int len = s.length();
for (int i = 1; i < len; i++) {
set.add(s.charAt(i));
for (int j = i - 1; j >= 0; j--) {
char c2 = s.charAt(j);
if (set.contains(c2)) {
index = 1;
set.clear();
break;
} else {
index++;
set.add(c2);
}
result = Math.max(result, index);
}
index = 1;
set.clear();
}
return result;
}
}
思路:
以为例:abcabcbb
一次遍历每个字符,作为一轮
第1轮:
1个字母a时,a前面无字符
第2轮: 2个字符时,依次从后往前遍历并存入map,如果当前遍历的字符在map中则停止
ba
第3轮:
cba
第4轮:
acb a
当再遍历到a时,map中已经存在了,则停止次轮循环,继续下一轮:
第5轮:
bac b...
max值每次更新
时间复杂度:O(N^2) n为数组长度
空间复杂度:O(N)
解法2 滑动窗口
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length() == 0) {
return 0;
}
int maxLen = 1;
HashSet<Character> set = new HashSet<>();
set.add(s.charAt(0));
int len = s.length();
int right = 1;
for (int i = 0; i < len; i++) {
if (i != 0) {
set.remove(s.charAt(i - 1));
}
while (right < len) {
char cK = s.charAt(right);
if (set.contains(cK)) {
break;
}
set.add(cK);
maxLen = Math.max(maxLen, right - i + 1);
right++;
}
}
return maxLen;
}
}
用左右指针分别记录,中间的是不重复的字符set。
每次移动右指针,一旦当前元素在set中,则将左指针右移一步。
时间复杂度:O(N) n为数组长度,左右指针分别会遍历这个那个字符串一次
空间复杂度:O(N)
解法3: 滑动窗口优化
右指针每次移动过程中,左指针的更新为:max(左指针,map中已存在的值+1)
举个例子:
abcabcbb
依次遍历abc再到a时
右指针为3
左指针为0,
map.a = 0
变化为左指针变为 max(0, map.a + 1) = 1
pwwkew
依次遍历pw再到w时
右指针为2
左指针为0,
map.w = 1
变化为左指针变为 max(0, map.a + 1) = 2
class Solution {
public int lengthOfLongestSubstring(String s) {
int start = 0;
int len = s.length();
int res = 0;
HashMap<Character, Integer> map = new HashMap<>();
for (int end = 0; end < len; end++) {
if (map.containsKey(s.charAt(end))) {
start = Math.max(start, map.get(s.charAt(end)) + 1);
}
map.put(s.charAt(end), end);
res = Math.max(res, end - start + 1);
}
return res;
}
}
时间复杂度:O(N) n为数组长度
空间复杂度:O(N)