无重复字符的最长子串
描述
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
示例 4:
输入: s = “”
输出: 0
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
答案
答案一
1. 暴力解法:遍历数组的所有的区间,然后找到最长没有重复字符的区间
时间复杂度:O(n^3)
空间复杂度:O(n)
会超时
public static int lengthOfLonge1(String s) {
int result = 1;
if (s.isEmpty()) {
return result;
}
for (int i = 0; i < s.length(); i++) {
for (int j = i+1; j < s.length(); j++) {
if (allUnique(s,i,j)) {
result = Math.max(result,j-i+1);
}
}
}
return result;
}
private static boolean allUnique (String s, int i,int j) {
Set<Character> set = new HashSet<>();
for (int k = i; k <= j; k++) {
if (set.contains(s.charAt(k))) {
return false;
}
set.add(s.charAt(k));
}
return true;
}
答案二
2. 滑动窗口
时间复杂度:O(2n) = O(n),最坏的情况是 left 和 right 都遍历了一遍字符串
空间复杂度:O(n)
public static int lengthOfLonge2(String s) {
int n = s.length();
if (n<=1) {
return n;
}
int maxLen = 1;
int left = 0;
int right = 0;
Set<Character> window = new HashSet<>();
while (right < n) {
char rightChar = s.charAt(right);
while (window.contains(rightChar)) {
window.remove(s.charAt(left));
left ++;
}
maxLen = Math.max(maxLen, right-left+1);
window.add(rightChar);
right++;
}
return maxLen;
}
答案三
// 3. 优化后的滑动窗口 hashmap优化
// 时间复杂度:O(n)
// 空间复杂度:O(n)
public static int lengthOfLonge3(String s) {
int n = s.length();
if (n<=1) {
return n;
}
int maxLen = 1;
int left = 0;
int right = 0;
HashMap<Character,Integer> map = new HashMap<>();
while (right < n) {
Character rightChar = s.charAt(right);
int orDefault = map.getOrDefault(rightChar, -1);
left = Math.max(left, orDefault + 1);
maxLen = Math.max(maxLen,right-left+1);
map.put(rightChar,right);
right++;
}
return maxLen;
}
答案四
// 4. 追求程序的极致性能 数组优化
// s 由英文字母、数字、符号和空格组成
public static int lengthOfLonge(String s) {
int n = s.length();
if (n <= 1) return n;
int maxLen = 1;
int left = 0, right = 0;
int[] window = new int[128];
while (right < n) {
char rightChar = s.charAt(right);
int rightCharIndex = window[rightChar];
left = Math.max(left, rightCharIndex);
maxLen = Math.max(maxLen, right - left + 1);
window[rightChar] = right + 1;
right++;
}
return maxLen;
}