查找一個字符串中最長不含重複字符的子字符串,計算該最長子字符串的長度

前言:

算法題:查找一個字符串中最長不含重複字符的子字符串,計算該最長子字符串的長度;

下面將使用 滑動窗口 方法實現,並經過對滑動窗口算法一步步進行優化,使其空間和時間的消耗一步步下降;java

什麼是滑動窗口?

滑動窗口:通常是指 運行在一個大數組上的子數組,該大數組是一個底層元素集合

例如:假設有大數組 [ a b c d b e f d n ] ,設定一個大小爲 3 的小數組 爲 滑動窗口 ;則存在下面的窗口:算法

[a b c]
  [b c d]
    [c d b]
      [d b e]
        [b e f]
          [e f d]
            [f d n]

滑動窗口重要性質:數組

  1. 滑動窗口通常表示成一個 左閉右開區間
  2. 窗口的左邊界(指針 i)和右邊界(指針 j)永遠只能向右移動 ,而不能向左移動。

如圖:學習

使用滑動窗口解題

一、未優化的滑動窗口實現:

沒有任何優化的滑動窗口實現;優化

經過 指針 i 和 指針 j 不斷的向左移動,造成了一個個的窗口,而且在將窗口的字符存放到了 Set 集合中,使用 Set 集合判斷 即將 進入窗口中的字符(也就是指針 j 移動到指向的字符)是否在窗口已經存在;spa

  1. 若是已經存在:則計算此時窗口的大小,並將存放窗口字符的 Set 集合清空(清空是爲了存放下個窗口的字符),最後將 指針 i 向左移動一位,而後指針 j 也指向指針 i 的位置。
  2. 若是是不存在:則將此字符存放到 Set 集合窗口字符中 。
1.一、看圖理解:

1.二、代碼實現:
public class LeetCode {

    public static int lengthOfLongestSubstring(String s) {
        if (s == null){
            return 0;
        }
        if (s.length() == 1){
            return 1;
        }

        // set 用來存儲窗口的字符
        Set<Character> set = new HashSet();

        // 指針i
        int i = 0;
        // 指針j
        int j = i;
        // 最大長度
        int max = 0;

        char[] sc = s.toCharArray();
        while(j < sc.length && i <= j){
            // 當字符沒在窗口中
            if (!set.contains(sc[j])){
                set.add(sc[j]);
                // 指針j 移動
                j++;
            }else {
                // 若是字符在窗口中時, 獲得當前窗口中的字符個數
                int size = set.size();
                if (max < size){
                    max = size;
                }
                // 將set中存儲的字符清空
                set.clear();
                // 指針i 移動
                i++;
                // 指針j 移動到指針i 的位置
                j = i;
            }
        }
        // 當指針j 移動到字符串尾部時, 窗口中可能還存在字符
        if (set.size() > max){
            max = set.size();
            set.clear();
            set = null; // help GC
        }

        return max;
    }


    public static void main(String[] args) {
        System.out.println(lengthOfLongestSubstring("abcdbefdn"));
    }

}
1.三、執行效果(來自LeetCode):

1.四、未經優化的滑動窗口的缺點:
缺點一:

存在不少無用的重複的 滑動窗口指針

例如:字符串 abcdbefdn,根據上面實現的滑動窗口方法,會獲得如下窗口:[ a b c d ]、[ b c d ]、[ c d b e f ]、[ d b e f ]、[ b e f d n ] 這 5 個滑動窗口;下面錯位展現更直觀,會發現 [ b c d ]、 [ d b e f ] 這兩個滑動窗口顯然被包含在其以前的窗口中,它們被重複統計了。code

[ a b c d ]

  [ b c d ]

    [ c d b e f ]

      [ d b e f ]

        [ b e f d n ]
缺點二:

存儲 滑動窗口中 字符的 Set 集合存在反覆 清空,再次存入字符的狀況;而且存在字符被重複存入 Set 集合中。blog

二、優化後的滑動窗口實現:

優化點:rem

  1. 直接將指針 i 指向出現的重複字符的位置,滑動窗口大小爲 (j - i),這樣就將無用的重複的 滑動窗口 跳過,這樣會大大縮短執行時間;
  2. 存放滑動窗口的字符容器改成 Map 集合,key爲 字符,value 爲字符下標;而且再也不清空集合了,而是遇到重複字符後,更新此字符的下標位置;

    例如:一開始 字符 b 在map集合中的value 位置爲1,當再次遇到下標爲 3 的字符 b 後,將map集合中的value 下標 由 1 改成 3

2.一、看圖理解:

2.二、代碼實現:
public class LeetCode {

    public static int lengthOfLongestSubstring(String s) {
        if (s == null){
            return 0;
        }
        if (s.length() == 1){
            return 1;
        }
        // map 用來存儲窗口字符, key是字符, value爲字符在字符串中的下標位置
        Map<Character, Integer> map = new HashMap<Character, Integer>();

        // 指針j
        int j = 0;
        // 重複字符的位置, 默認爲-1
        int i = -1;
        // 最大長度
        int max = 0;

        char[] sc = s.toCharArray();
        while(j < sc.length){
            if (map.containsKey(sc[j])){
                // 獲取map中重複字符的位置
                int index = map.get(sc[j]);
                if (index > i){
                    i = index;
                }
            }
            // 指着j - 重複字符的位置 = 當前窗口的大小
            if ((j-i) > max){
                max = j-i;
            }
            // 若是map中存在重複字符的話,這裏是將字符的位置進行更新 ; 若是不是重複字符的話,就直接存放到map中
            map.put(sc[j], j);
            j++;
        }
        map.clear();
        map = null; // help GC

        return max;
    }

    public static void main(String[] args) {
        System.out.println(lengthOfLongestSubstring("abcdbefdn"));
    }
}
2.三、執行效果(來自LeetCode):

上面就是通過了代碼優化後獲得的執行效果,發現執行時間大大縮短了;可是這可能還不是最優的,可能還存在最優的方法。

❤不要忘記留下你學習的足跡 [點贊 + 收藏 + 評論]嘿嘿ヾ

一切看文章不點贊都是「耍流氓」,嘿嘿ヾ(◍°∇°◍)ノ゙!開個玩笑,動一動你的小手,點贊就完事了,你每一個人出一份力量(點贊 + 評論)就會讓更多的學習者加入進來!很是感謝! ̄ω ̄=
相關文章
相關標籤/搜索