给定一个字符串,找出不含有重复字符的最长子串的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 无重复字符的最长子串是 "abc",其
长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 无重复字符的最长子串是 "b"
,其长度为 1。
示例 3:
输入: "pwwkew" 输出: 3 解释: 无重复字符的最长子串是"wke"
,其长度为 3。 请注意,答案必须是一个子串,"pwke"
是一个子序列 而不是子串。
解题思路
用left和right设置左右指针,分别标识字符串不重复字段的左部和右部。右指针不断移动直到遇到重复字符,同事更新长度。
当右指针所指元素已经查找过是,将左指针移到重复元素的后一位。
方法一:
用set方法,进而用contain判断是否重复
class Solution { public int lengthOfLongestSubstring(String s) { int res = 0, left = 0, right = 0; //滑动窗口解法1:set结构 Set<Character> set = new HashSet<>(); while(right < s.length()){ //contains是包涵的意思,就是用来检查有没有在录入的连续的map里面 if(!set.contains(s.charAt(right))){ set.add(s.charAt(right++)); res = Math.max(res,set.size()); }else{ //左指针向右移动,直到移动到重复元素 set.remove(s.charAt(left++)); } } return res; } }
方法二:
用的map方法,这里一开始没太弄懂,原来是吧left指针移至容器内的字符后一位,一开始理解错了。
class Solution { public int lengthOfLongestSubstring(String s) { //滑动窗口解法:map结构 Map<Character,Integer> map = new HashMap<>(); int res = 0; for(int left = 0, right = 0; right < s.length(); right++ ){ if(map.containsKey(s.charAt(right))){
//需要向后移至到重复字符后一位 left = Math.max(left, map.get(s.charAt(right)) + 1); } res = Math.max(res, right - left + 1); //根据map的性质,当存储重复元素时,新的value值即索引将会覆盖旧值 map.put(s.charAt(right), right); } return res;
abcacs } }
方法三:
这里我们可以建立一个256位大小的整型数组来代替HashMap,这样做的原因是ASCII表共能表示256个字符,所以可以记录所有字符,然后我们需要定义两个变量res和left,其中res用来记录最长无重复子串的长度,left指向该无重复子串左边的起始位置,然后我们遍历整个字符串,对于每一个遍历到的字符,如果哈希表中该字符串对应的值为0,说明没有遇到过该字符,则此时计算最长无重复子串,i - left +1,其中i是最长无重复子串最右边的位置,left是最左边的位置,还有一种情况也需要计算最长无重复子串,就是当哈希表中的值小于left,这是由于此时出现过重复的字符,left的位置更新了,如果又遇到了新的字符,就要重新计算最长无重复子串。最后每次都要在哈希表中将当前字符对应的值赋值为i+1。代码如下:
class Solution { public int lengthOfLongestSubstring(String s) { //滑动窗口方法:数组存储ASCII值 int[] m = new int[256]; int res = 0; //try extend the rang [left, right] for(int left = 0, right = 0; right < s.length(); right++){ //m[s.charAt(right)]返回一个重复字符的地址 left = Math.max(m[s.charAt(right)], left); res = Math.max(res, right - left + 1); m[s.charAt(right)] = right + 1; } return res; } }
分析表格
0 | 1 | 2 | 3 | 4 | 5 | 6 |
a | b | c | a | b | c | a |
right | left | res |
m[s.charAt(right)]
|
0 | 0 | 1 | 1 |
1 | 0 | 2 | 2 |
2 | 0 | 3 | 3 |
3 | 1 | 3 | 4 |
4 | 2 | 3 | 5 |