一、题目概述
二、思路方向
为了找出给定字符串中不含有重复字符的最长子串的长度,我们可以使用滑动窗口的方法。这种方法通过维护一个窗口(或称为子串),并动态地调整窗口的左右边界来找到最长的无重复字符子串。
三、代码实现
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
if (n == 0) return 0;
// 使用HashMap来存储字符及其最近出现的位置
Map<Character, Integer> map = new HashMap<>();
int maxLength = 0; // 最长无重复字符子串的长度
int left = 0; // 窗口左边界
for (int right = 0; right < n; right++) {
char c = s.charAt(right);
// 如果字符c已经在map中,并且其位置在窗口内(即大于等于left),则移动左边界
if (map.containsKey(c) && map.get(c) >= left) {
left = map.get(c) + 1;
}
// 更新字符c的最新位置
map.put(c, right);
// 更新最长无重复字符子串的长度
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}
public static void main(String[] args) {
Solution solution = new Solution();
String s = "abcabcbb";
System.out.println("Length of longest substring without repeating characters: " + solution.lengthOfLongestSubstring(s));
}
}
解释
初始化:我们初始化一个HashMap来存储每个字符最近一次出现的位置,以及一个变量
maxLength
来记录最长无重复字符子串的长度。我们还设置两个指针left
和right
来定义当前考虑的子串的边界。遍历字符串:我们使用
right
指针遍历字符串的每个字符。对于每个字符,我们检查它是否已经在HashMap中,并且其位置是否在当前的窗口内(即大于等于left
)。如果是,我们需要移动left
指针到该字符上一次出现位置的下一个位置,以确保窗口内没有重复字符。更新HashMap和maxLength:然后,我们更新HashMap中当前字符的位置为
right
,并检查是否需要更新maxLength
。返回结果:遍历完成后,
maxLength
将包含最长无重复字符子串的长度,我们将其返回。
执行结果:
四、小结
这种方法的时间复杂度是O(n),因为我们只遍历了字符串两次(一次是
right
指针,一次是可能的left
指针移动),而HashMap的插入和查找操作都是O(1)的。空间复杂度也是O(min(m, n)),其中m是字符集的大小(对于ASCII字符集,m=128),n是字符串的长度。在最坏的情况下,我们需要存储字符串中的所有不同字符。然而,由于字符集通常远小于字符串长度,因此可以认为空间复杂度是O(min(m, n)),但在实际应用中,它通常接近O(m)。
结语
勇气不是没有恐惧,而是即便恐惧也依然前行
信心不是没有疑虑,而是即便疑虑也依然坚持
!!!