LeetCode-3-无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
解题思路
方法1、哈希表:
首先挨个比较i个字符和i+1结合哈希的方法是失败的,这样求的不适用于dvdf
这样的测试用例
我们可以通过记录无重复字符的初始位置start,以及结尾位置end,算出最长的字串是多大
顺序遍历整个字符数组,判断当前的元素是否在hash表内,如果在则将当前元素作为key值,获取不重复元素对应位置,并更新start,此时,start到end不存在重复字符
进入下一步,计算区间内字符长度
如果当前元素不在hash表内,则添加当前字符位置+1,+1表示从当前字符位置后面一个开始不重复
方法2、滑动窗口:
窗口的最大值就是最长字串,比如dvdf
这样的用例
当窗口为dv
的时候,满足题目要求,当窗口为dvd
时,不满足要求,此时需要向右边滑动
将左边重复的元素d移除,同时在右边新增,直到满足要求为止
当窗口变化的时候记录当前窗口的最大值
方法3、Set+滑动窗口:
利用HashSet存储遍历过的字符串,同时创建left
和right
指针分别代表字符串的最长子串开头和结尾位置,遍历例如abcabcbb
时,右指针right
小于字符c
的长度时,right
右移增大窗口内的元素。当当前最长子串为abc
时,遍历到后一个字符发现为a
,此时出现重复,需要收缩窗口。left++
,左窗口移动,同时移除set
中的最左元素,直到符合规定为止。之后判断当前的子串长度和最长子串长度谁更大即可。当前的子串长度可以由right-left
获得。
Java代码
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> map = new HashMap<>();
char[] c = s.toCharArray();
int max = 0;
int start = 0;
for (int end = 0; end < c.length; end++) {
if (map.containsKey(c[end])) {
start = Math.max(map.get(c[end]), start);
}
max = Math.max(max, end - start + 1);
map.put(c[end], end + 1);
}
return max;
}
}
Python代码
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s: return 0
left = 0
Max,curMax = 0,0
n = len(s)
hashset = set()
for i in range(n):
curMax += 1
while s[i] in hashset:
hashset.remove(s[left])
left += 1
curMax -= 1
if curMax > Max: Max = curMax
hashset.add(s[i])
return Max
Java代码2
class Solution {
public int lengthOfLongestSubstring(String s) {
HashSet<Character> set = new HashSet<>();
char[] c = s.toCharArray();
int left = 0;
int right = 0;
int max = 0;
while (right < c.length) {
char nowC = c[right];
right++;
while (set.contains(nowC)) {
set.remove(c[left]);
left++;
}
max = Math.max(max, right - left);
set.add(nowC);
}
return max;
}
}