无重复字符的最长字串
- 电脑硬件
- 2025-08-06 13:00:03

题目
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例示例 1:
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。示例 2:
输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。示例 3:
输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 思想(滑动窗口)滑动窗口是一种在数组或字符串上进行迭代的算法,通过维护一个子数组或子串,该子数组或子串的大小在迭代过程中可以变化。该子数组或子串的起始位置通过"滑动"进行调整,从而找到符合特定条件的解。
滑动窗口的窗口大小是动态变化的,当发现重复字符时,通过调整窗口的起始位置来实现。这样,你能够在遍历字符串的过程中找到不包含重复字符的最长子串,同时利用 `max` 变量来记录最大长度。
滑动窗口是解决一类子串或子数组问题的常见思想,通常用于解决找到不重复元素的最长子串或子数组的问题。这种方法的优势在于它可以在线性时间内解决问题,而不需要嵌套循环。
算法分析1. 初始化变量:`max` 用于存储最长子串的长度,`index` 用于跟踪重复字符的索引,空字符串 `str` 用于存储当前子串。
2. 使用 for 循环遍历输入字符串 `s` 中的每个字符。
3. 在循环内部,通过使用 `indexOf` 方法检查当前字符 `ch` 是否已经存在于当前子串 `str` 中。如果存在(`index != -1`),则表示找到了重复的字符。
4. 如果找到重复的字符,通过比较当前子串 `str` 的长度和当前最大长度 `max` 来更新 `max` 长度。然后,通过删除从子串开头到重复字符(包括重复字符)的字符来更新子串 `str`,并将当前字符 `ch` 连接到子串中。
5. 继续循环。
6. 如果未找到重复字符,简单地将当前字符 `ch` 连接到子串 `str` 中。
7. 循环结束后,比较最终子串 `str` 的长度和当前最大长度 `max`,以确保最后一个子串也被考虑在内。
8. 返回最大长度。
class Solution { public int lengthOfLongestSubstring(String s) { int max=0; int index=-1; String str=""; for(int i=0;i<s.length();i++){ char ch=s.charAt(i); index=str.indexOf(ch); if(index!=-1){ max=Math.max(str.length(),max); str=s.substring(i-(str.length()-1-index),i+1); continue; } str=str+ch; } max=Math.max(str.length(),max); return max; } } 运行结果总的时间复杂度为 O(n)
击败百分之5%的对手。。。emmm被我击败南坪
算法调优这时官方的解法,思想也是滑动窗口,来看看有什么区别:
时间复杂度是O(n^2)
它采用一个Set集合,然后左指针指向i ,右指针指向rk
rk从一个开始逐个遍历,增加不同的值加入集合,
一旦有相同的值,就说明此i指向的值的最长长度已经到了,让左指针i++,指向下一个值。
rk不用更新回去,因为从i到rk是不重复的,那从i+1到rk也肯定是不重复的,所以rk不用更新回去,set集合也不用清空。
每次左指针移动前,要更新最长的长度
Set<Character> occ = new HashSet<Character>();: 创建一个哈希集合 occ,用于记录当前窗口中字符的出现情况。
int rk = -1, ans = 0;: 定义右指针 rk 初始值为 -1,用于表示当前窗口的右边界。ans 用于记录最长子串的长度。
occ.remove(s.charAt(i - 1));: 在每次移动左指针时,从哈希集合中移除左指针所指向的字符,表示该字符不再属于当前窗口。
while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) { ... }: 在每次移动右指针时,不断地向右移动,直到遇到重复字符或者到达字符串的末尾。在移动的过程中,将新的字符加入哈希集合。
ans = Math.max(ans, rk - i + 1);: 在每一步迭代中,更新最长子串的长度。
class Solution { public int lengthOfLongestSubstring(String s) { // 哈希集合,记录每个字符是否出现过 Set<Character> occ = new HashSet<Character>(); int n = s.length(); // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动 int rk = -1, ans = 0; for (int i = 0; i < n; ++i) { if (i != 0) { // 左指针向右移动一格,移除一个字符 occ.remove(s.charAt(i - 1)); } while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) { // 不断地移动右指针 occ.add(s.charAt(rk + 1)); ++rk; } // 第 i 到 rk 个字符是一个极长的无重复字符子串 ans = Math.max(ans, rk - i + 1); } return ans; } }时间耗时:6ms确实比我块的多,但是时间复杂度很大。懂得都懂
无重复字符的最长字串由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“无重复字符的最长字串”