3. 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
法一:
1 public class Solution { 2 public int lengthOfLongestSubstring(String s) { 3 int ans = 0; 4 HashMap<Character,Integer> map = new HashMap<>(); 5 for(int i = 0 ,j = 0 ;j < s.length(); j++ ){ 6 if(map.containsKey(s.charAt(j))){ 7 i = Math.max(map.get(s.charAt(j)) + 1 , i); 8 } 9 map.put(s.charAt(j),j); 10 ans = Math.max(ans, j - i + 1); 11 } 12 return ans; 13 } 14 }
i为起始窗口start,j为终点窗口end,利用滑窗思想,map中存放每一个字母和其最后出现的序列号,当end出现重复字母,即将start更新到map中该重复字母的下一位。
如果end字母不在map中,则存入map,记录序列号;
如果end字母在map中,则更新start,滑动起始窗口,(需注意,要比较原start序列号和重复字母序列号,不能直接更新start,防止指针回跳,例如cabac,当a重复,start更新到b处,接着end滑到c时,map中c位序为0,但c已经不再滑动窗口中,不能更新start,否则造成指针start回跳到c处)再更新map中重复字母位序
最后比较当前子串和记录最长子串大小
法二:
1 public class Solution2 { 2 public int lengthOfLongestSubstring(String s) { 3 HashSet<Character> set = new HashSet<>(); 4 int i = 0, j = 0, ans = 0; 5 while( j < s.length()){ 6 if(set.contains(s.charAt(j))) { 7 set.remove(s.charAt(i)); 8 i++; 9 }else { 10 set.add(s.charAt(j)); 11 ans = Math.max(ans, j - i + 1); 12 j++; 13 } 14 } 15 return ans; 16 } 17 }
利用HashSet记录不重复字母,当出现重复字母时,按照start的后移顺序,依次剔除,直至删除到end重复字母,保持set中始终为当前end字母情况下的最短不重复子串,最后更新ans为最大值
法三:
1 class Solution3 { 2 public int lengthOfLongestSubstring(String s) { 3 char[] charArr = s.toCharArray(); 4 if (charArr.length == 0) { 5 return 0; 6 } 7 int maxLength = 0; 8 int baseIndex = 0; 9 int i; 10 11 //i从第二个元素开始 12 for (i = baseIndex + 1; i < charArr.length; i++) { 13 14 //j从base开始,从前往后找,与第i个相同的元素,并且计算长度 15 for (int j = baseIndex; j < i; j++) { 16 17 //如果找到相同元素,base直接跳到当前元素下一个 18 if (charArr[j] == charArr[i]) { 19 maxLength = (i - baseIndex) > maxLength ? (i - baseIndex) : maxLength; 20 baseIndex = j + 1; 21 break; 22 } 23 } 24 } 25 26 //全部遍历后还要再计算一次,如果直到最后一位还没有重复元素的情况 27 maxLength = (i - baseIndex) > maxLength ? (i - baseIndex) : maxLength; 28 return maxLength; 29 } 30 }
将字符串转为字符数组,利用双脚标ij,起始脚标baseIndex,当i每次后移一位,j从baseIndex开始后移直至找到与arr[i]相同字母,则i-baseIndex为该次最长不重复子串,更新baseIndex,再次移动i,直至结束。
例如cabae,当arr[1]=arr[3]=a时,去掉arr[3],cab即为最长不重复子串,更新baseIndex = j + 1。
浙公网安备 33010602011771号