题目描述:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例:
输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 输入: "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
题目难度:中等
分析:
方法一:暴力法
首先最容易想到的就是暴力解法,列出所有的子字符串,然后逐个检查是否包含重复的字符就行了,这样思路很简单,但是效率太慢,不推荐。
代码省略…因为太麻烦了,懒得写。
小结:
时间复杂度为O ( n 3 )
方法二:
滑动窗口。比较常用的算法之一,用来解此题比较合适,思路就是通过两个指针 i 和 j ,然后不断的右移 j 来确定 在范围 [i, j) 中是否存在和s[j]相同的元素,假设这个元素的下标为n如果存在那么就可以跳过[i, n]这区间,此时的左指针 i 就变为 n + 1。代码如下:
java:
class Solution { public int lengthOfLongestSubstring(String s) { // 定义最大长度 int maxLength = 0; int l = s.length(); // 用来检查字符是否存在的map,key为字符,value为索引 Map<Character, Integer> map = new HashMap<>(); for (int i = 0, j = 0; j < l; j++) { // 如果当前字符已经存在与map那么可以跳过,左指针i和这个字符的索引取较大值,作为当前左指针i的索引位置 if (map.containsKey(s.charAt(j))) { i = Math.max(map.get(s.charAt(j)), i); } // 最大长度就是:右指针j - 左指针i 别忘了 + 1 maxLength = Math.max(maxLength, j - i + 1); // 把这个字符放入map中 map.put(s.charAt(j), j + 1); } return maxLength; } }
python:
class Solution: def lengthOfLongestSubstring(self, s: str) -> int: i = j = max_length = 0 map = {} l = len(s) while j < l: if s[j] in map: i = max(i, map[s[j]]) max_length = max(max_length, j - i + 1) map[s[j]] = j + 1 j += 1 return max_length
小结:
时间复杂度为O ( n )
总结:
滑动窗口是算法当中比较常用的一种套路,用来计算数组和字符串类的问题比较高效。必须要掌握,看见这类问题应该第一时间就想到这种解决办法。