讓我們一起啃演算法----無重複字元的最長子串

三斤和他的喵發表於2020-04-09

無重複字元的最長子串

這是 LeetCode 第三題,題幹如下:

給定一個字串,請你找出其中不含有重複字元的 最長子串 的長度。
示例 1:
  輸入: “abcabcbb”
  輸出: 3
  解釋: 因為無重複字元的最長子串是 “abc”,所以其長度為 3。
示例 2:
  輸入: “bbbbb”
  輸出: 1
  解釋: 因為無重複字元的最長子串是 “b”,所以其長度為 1。
示例 3:
  輸入: “pwwkew”
  輸出: 3
  解釋: 因為無重複字元的最長子串是 “wke”,所以其長度為 3。請注意,你的答案必須是 子串 的長度,”pwke” 是一個子序列,不是子串。

解題思路

常規思路:兩層迴圈字串,並且我們需要一個 Map字典 來標記哪些字元已經出現過,流程如下:

GO語言的程式碼實現:

func lengthOfLongestSubstring(s string) (length int) {
    if "" == s {
        return
    }
    length = 1
    for i := 0; i < len(s); i++ {
        // 字元的ASCII範圍在0-127,所以這裡申明瞭map的key型別為uint8
        dict := make(map[uint8]bool)
        dict[s[i]] = true
        for j := i + 1; j < len(s); j++ {
            // 判斷字元是否在map中,如果存在就直接跳出迴圈
            if _, ok := dict[s[j]]; ok {
                break
            }
            // 將字元放入map中
            dict[s[j]] = true
            // 每次都計算最大值
            cMax := j - i + 1
            if cMax > length {
                length = cMax
            }
        }
    }
    return
}

這個題目,其實主要的考點在於對 滑動視窗 的理解。

滑動視窗:滑動視窗是陣列、字串問題中常用的抽象概念。
視窗通常是在陣列、字串中由開始和結束索引定義的一系列元素的集合,即 [i, j)(左閉,右開)。
而滑動視窗是可以將兩個邊界向某一方向“滑動”的視窗。例如,我們將 [i, j) 向右滑動 1 個元素,
則它將變為 [i+1, j+1)[i+1,j+1)(左閉,右開)。

那麼借用 滑動視窗 的概念,如何來解題呢?我這裡畫了一張示意圖,其中 [X,Y) 就是 滑動視窗

這裡有一個注意點:當 Y 指向的字元在 [X,Y) 滑動視窗之間時,假設索引值為 index,這時候 X 是直接移動到 index+1 的位置。
GO語言的程式碼實現:

func lengthOfLongestSubstring(s string) int {
    var Length int
    var s1 string
    x := 0
    y := 0
    s1 = s[x:y]
    for ; y < len(s); y++ {
        // strings.IndexByte 用於判斷y對應的字元是否在[x,y)中,不存在返回-1
        if index := strings.IndexByte(s1, s[y]); index != -1 {
            // 如果存在的話,x直接跳到index的後一位
            x += index + 1
        }
        s1 = s[x : y+1]
        if len(s1) > Length {
            Length = len(s1)
        }
    }
    return Length
}

總結

每天進步一點點,加油!
完整程式碼:https://github.com/wx-satellite/go-leetcod…

本作品採用《CC 協議》,轉載必須註明作者和本文連結

三斤

相關文章