1. 问题描述
Given a string, find the length of the longest substring without repeating characters.
Examples:Given
"abcabcbb"
, the answer is"abc"
, which the length is3
.
Given"bbbbb"
, the answer is"b"
, with the length of1
.
Given"pwwkew"
, the answer is"wke"
, with the length of3
.
Note that the answer must be a substring,"pwke"
is a subsequence and not a substring.
2. 解法描述
2.1 暴力穷举
最直接的思路是遍历每个可能的子串,然后判断子串是否有重复字符,最后返回符合条件的各子串长度中的最大值,代码如下:
public static int lengthOfLongestSubstring1(String s) {
int len = s.length();
int ans = 1;
for (int curr1 = 0; curr1 < len - 1; curr1 ++) {
for (int curr2 = curr1 + 1; curr2 < len; curr2 ++) {
if (isUnique(s, curr1, curr2)) ans = Math.max(ans, curr2 - curr1 + 1);
}
}
return ans;
}
public static boolean isUnique(String s, int start, int end) {
Set<Character> set = new HashSet<>(); // 集合内元素唯一性
for (int i = start; i <= end; i ++) {
Character ch = s.charAt(i);
if (set.contains(ch)) return false;
set.add(ch);
}
return true;
}
时间复杂度为
O(n3)
,空间复杂度为
O(min(m,n))
,其中
n
为字符串长度,
2.2 优化版本
显然,暴力穷举法是不可接受的。
对于判断某元素是否重复这类问题,首先想到的是集合set
(在暴力穷举法中的isUnique
方法上已使用),另外,还有一种集合不易想到,那就是map
(key值唯一)。
2.2.1 set
版本
设置两个游标curr1
、curr2
,两游标间的最大间隔即为待求结果。
public static int lengthOfLongestSubstring2(String s) {
int len = s.length();
Set<Character> set = new HashSet<>();
int ans = 0, curr1 = 0, curr2 = 0;
while (curr1 < len && curr2 < len) {
if (set.contains(s.charAt(curr2))) {
set.remove(s.charAt(curr1++));
} else {
set.add(s.charAt(curr2++));
ans = Math.max(ans, curr2 - curr1);
}
}
return ans;
}
时间复杂度为 O(2n)=O(n) ,空间复杂度同样为 O(min(m,n)) 。
2.2.2 map
版本
set
版本的问题在于curr1
不能直接移到已重复元素的上一位,而这个问题主要由集合set
的存储结构所决定的。而map
不仅能够存储值,还能够存储值所对应的下标。
public static int lengthOfLongestSubstring3(String s) {
int len = s.length();
Map<Character, Integer> map = new HashMap<>();
int ans = 0;
for (int curr1 = 0, curr2 = 0; curr2 < len; curr2++) {
if (map.containsKey(s.charAt(curr2))) {
curr1 = Math.max(curr1, map.get(s.charAt(curr2)) + 1);
} else {
ans = Math.max(ans, curr2 - curr1 + 1);
map.put(s.charAt(curr2), curr2 + 1);
}
}
return ans;
}
时间复杂度为 O(n) ,空间复杂度同样为 O(min(m,n))