Leetcode Sliding Window

剑指 Offer 59 - I. 滑动窗口的最大值

题目

  • 解法 在滑窗基础上利用双向队列维护最大值备选有序队列 dq 可以采取不同数据结构,如果想节省内存,可以用container/list 本题对内存不敏感,所以提前声明一个较长的 slice
func maxSlidingWindow(nums []int, k int) []int {
    if len(nums) < k {
        return nil
    }

    res := make([]int, 0, len(nums) - k + 1)
    dq := make([]int, 0, len(nums))

    for i, num := range nums {
        // 最大值弹出
        if i >= k && len(dq) > 0 && dq[0] == nums[i - k] {
            dq = dq[1:]
        }

        // 加入备选有序队列
        for len(dq) > 0 && dq[len(dq)-1] < num {
            dq = dq[:len(dq)-1]
        }
        dq = append(dq, num)

        if i + 1 >= k {
            res = append(res, dq[0])
        }
    }

    return res
}

“214. Shortest Palindrome” RollingHash

func shortestPalindrome(s string) string {
    n := len(s)
    Base, Mod := 26, int(1e7+1)
    left, right, factor, best := 0, 0, 1, -1
    for i := 0; i < n; i++ {
        left = (left*Base + int(s[i]-'0')) % Mod
        right = (right + int(s[i]-'0')*factor) % Mod
        if left == right {
            best = i
        }
        factor = factor * Base % Mod
    }
    var add []byte
    if best != n-1 {
        add = []byte(s[best+1:])
    }
    for l,r := 0, len(add)-1; l < r; l,r = l+1,r-1{
        add[l], add[r] = add[r], add[l]
    }
    return string(add) + s
}s

“424. Longest Repeating Character Replacement”

func characterReplacement(s string, k int) int {
    l, maxCnt, cnt := 0, 0, make([]int, 26)
    for r, c := range s {
        cnt[c-'A']++
        maxCnt = max(maxCnt, cnt[c-'A'])
        if maxCnt + k < r - l + 1 {
            cnt[s[l]-'A']--
            l++
        }
    }
    return len(s)-l
}

“1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit” SlidingWindow+MonotoneQueue Golang

func longestSubarray(nums []int, limit int) (ret int) {
    left := 0
    var minQue, maxQue []int
    for right, v := range nums {
        for len(minQue) > 0 && minQue[len(minQue)-1] > v {
            minQue = minQue[:len(minQue)-1]
        }
        minQue = append(minQue, v)
        for len(maxQue) > 0 && maxQue[len(maxQue)-1] < v {
            maxQue = maxQue[:len(maxQue)-1]
        }
        maxQue = append(maxQue, v)
        for len(maxQue) > 0 && len(minQue) > 0 &&
        (maxQue[0] - minQue[0] > limit) {
            if nums[left] == maxQue[0] {
                maxQue = maxQue[1:]
            }
            if nums[left] == minQue[0] {
                minQue = minQue[1:]
            }
            left++
        }
        ret = max(ret, right-left+1)
    }
    return ret
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

“395. Longest Substring with At Least K Repeating Characters” Golang

func longestSubstring(s string, k int) (ret int) {
    for n := 1; n <= 26; n++ {
        // 窗口内字母种类、窗口内小于k个的字母种类、左边
        var setSize, lessK, l int
        var record [26]int  // 窗内字母数量统计
        for r, c := range s {
            index := c-'a'
            if record[index] == 0 {
                setSize++
                lessK++
            }
            record[index]++
            if record[index] == k {
                lessK--
            }

            for setSize > n {
                idx := s[l]-'a'
                if record[idx] == k {
                    lessK++
                }
                record[idx]--
                if record[idx] == 0 {
                    setSize--
                    lessK--
                }
                l++
            }

            if lessK == 0 {
                ret = max(ret, r-l+1)
            }
        }
    }
    return ret
}

“1044. Longest Duplicate Substring” RollingHash

func longestDupSubstring(s string) (ret string) {
    find := func(k int) string {
        if k == 0 {return ""}
        m := make(map[int64][]int, len(s)-k+1)  // map[hashCode][]index
        var hashCode int64
        pow := Power(k)
        for i := range s {
            hashCode *= MOD
            if i >= k {
                hashCode -= int64(s[i-k]) * pow
            }
            hashCode += int64(s[i])
            if i < k-1 {
                continue
            }
            if sli, ok := m[hashCode]; ok {
                for _, idx := range sli {
                    if string(s[i-k+1:i+1]) == string(s[idx: idx+k]) {
                        return string(s[i-k+1:i+1])
                    }
                }
            }

            m[hashCode] = append(m[hashCode], i-k+1)
        }
        return ""
    }

    l, r := 0, len(s)
    for l+1 < r {
        mid := (l+r)>>1
        if ret = find(mid); ret != "" {
            l = mid
        } else {
            r = mid
        }
    }

    return find(l)
}


const MOD = 26
func Power(y int) (ret int64) {
    for ret = 1; y > 0; y-- {
        ret *= MOD
    }
    return ret
}

“1316. Distinct Echo Substrings”

// RollingHash
func distinctEchoSubstrings(text string) (ret int) {
    const Mod = 1e9+7
    n := len(text)
    maxLen := n/2
    set := make(map[string]bool)
    for length := 1; length <= maxLen; length++ {
        hash1, hash2, factor := 0, 0, 1
may_colission:
        for i := 0; i < n; i++ {
            if i < length {
                hash1 = (hash1*26 + int(text[i]-'a'))%Mod
                if i > 0 {
                    factor = (factor*26)%Mod
                }
            } else if i < 2*length {
                hash2 = (hash2*26 + int(text[i]-'a'))%Mod
            } else {
                hash1 = hash1 - int(text[i-2*length]-'a')*factor
                hash1 = (hash1*26 + int(text[i-length]-'a'))%Mod
                hash2 = hash2 - int(text[i-length]-'a')*factor
                hash2 = (hash2*26 + int(text[i]-'a'))%Mod
            }
            if i >= 2*length-1 && hash1 == hash2 && !set[text[i-length+1:i+1]] {
                for j := 0; j < length; j++ {
                    if text[i-j] != text[i-length-j] {
                        continue may_colission
                    }
                }
                ret++
                set[text[i-length+1:i+1]] = true
            }
        }
    }
    return ret
}

“1392. Longest Happy Prefix”

func longestPrefix(s string) (ret string) {
    const MOD = 1e9+7
    const BASE = 26
    last := len(s)-1

    var preHash, postHash, pow int64 = 0, 0, 1
    for i := 0; i < last; i++ {
        preHash = (preHash*BASE + int64(s[i]-'a'))%MOD
        postHash = (postHash + int64(s[last-i]-'a') * pow)%MOD
        pow = (pow*BASE)%MOD
        if preHash == postHash {
            ret = s[:i+1]
        }
    }

    return ret
}