1.题干描述

给定一个字符串 s ,找出其中不含有重复字符的 最长子串 的长度。
示例 :

  1. 输入: s = "abcabcbb"
  2. 输出: 3
  3. 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3
  4. /**==================*/
  5. 输入: s = "bbbbb"
  6. 输出: 1
  7. 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1
  8. /**==================*/
  9. 输入: s = "pwwkew"
  10. 输出: 3
  11. 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3
  12. 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
  13. 提示:
  14. 0 <= s.length <= 5 * 104
  15. s 由英文字母、数字、符号和空格组成

2.题解

点击获取源码:小骄傲的github

2.1 solution1_滑窗思想

将字符串看成一个队列,每次都将队列的第一个元素作为队头计算 不含重复字符的最长子串的长度, 不断的移出左边的元素,直到计算完整个队列。
比如‘abcabcbb’看称一个队列,当入队到‘abc’时满足要求,当再进入a时,队列变成了abca,这时候不满足要求。此时向左移动队列即将左边的元素移出,直到满足要求,一直维持这样的队列,找出队列的最长的长度。

时间复杂度:O(N),其中N是字符串的长度。左指针和右指针分别会遍历整个字符串一次 ?
空间复杂度:O(∣Σ∣),其中Σ表示字符集(即字符串中可以出现的字符),∣Σ∣ 表示字符集的大小。
在本题中没有明确说明字符集,因此可以默认为所有 ASCII 码在 [0, 128)内的字符,即∣Σ∣=128。
我们需要用到哈希集合来存储出现过的字符,而字符最多有 ∣Σ∣个,因此空间复杂度为 O(∣Σ∣)。?

  1. public static int solution1(String str){
  2. if (str.length() == 0) return 0;
  3. HashSet<Character> hashSetTemp = new HashSet<>();
  4. int rk = -1,ans = 0;
  5. for (int i = 0; i<str.length();i++){
  6. if (i != 0){
  7. //左指针向右移动一格,移除一个字符
  8. hashSetTemp.remove(str.charAt(i-1));
  9. }
  10. while (rk + 1 < str.length() && !hashSetTemp.contains(str.charAt(rk+1))){
  11. //不断的移动右指针
  12. hashSetTemp.add(str.charAt(rk+1));
  13. ++rk;
  14. }
  15. ans = Math.max(ans, rk-i+1);
  16. }
  17. return ans;
  18. }

2.2 solution2_滑窗思想

将字符串看成一个队列,若存在重复字符时,左指针向右移动至被重复字符的下一个位置(例如,第2个w出现时,left移动至第一个w的下一个位置),根据hashmap特点,将携带着新位置的重复元素重新存入map中。
比如‘pwwkew’看称一个队列,当入队到‘pw’时满足要求,当再进入w时,队列变成了pww,此时左指针left指向被重复元素的下一个位置w=2,重复元素w重新存入map:(w,2),一直维持这样的队列,直到找出最大长度。

时间复杂度:O(N),其中N是字符串的长度。
空间复杂度:

  1. public static int solution2(String str){
  2. if (str.length() == 0) return 0;
  3. HashMap<Character, Integer> map = new HashMap<>();
  4. int max = 0;
  5. int left = 0;
  6. for (int i = 0;i<str.length();i++){
  7. if (map.containsKey(str.charAt(i))){
  8. //左指针向右移动至被重复元素的下一个位置
  9. left = Math.max(left, map.get(str.charAt(i))+1);
  10. }
  11. map.put(str.charAt(i), i);
  12. //取不含重复字符的字串的最长长度
  13. max = Math.max(max, i-left);
  14. }
  15. return max;
  16. }