类型一:长度不固定的滑动窗口,求最长/最大问题

94 阅读4分钟

一、滑动窗口

  • 本质:固定左端点,不断枚举右端点,  不满足条件时缩短左端点
  • 题目条件:满足 单调性(数组元素都是正数) 的 子数组(数组元素连续)

二、思路

  • 关键词:

    • 子串/子数组必定连续,且单调性(即同为正数)
    • 求长度最长、频率最高、数目最多等
  • 难点在于:

    • 使用if还是for
    • 最值结果通常是right-left+1来更新
    • 统计数目使用map

三、题目汇总

四、题解汇总

  • Code 3

image.png

  • “不含有重复字符”,即可使用map。
  • “最长子串”,“子串”即连续,子串可想到滑动窗口,使用两指针,“最长”,即可定义一个变量存储最值,持续更新。
func lengthOfLongestSubstring(s string) int {
    maxLen:=0 // 定义一个变量存储最值
    strsMap:=map[byte]int{} // “不含有重复字符”,即可使用map
    left:=0
    for i:=0;i<len(s);i++{
        strsMap[s[i]]++ // 扩张窗口
        for strsMap[s[i]]>1{ // 收缩窗口的条件:一旦含有重复子串,即可收缩,左移指针
            strsMap[s[left]]-- 
            left++ 
        }
        maxLen=max(maxLen,i-left+1) // 更新最值,只要走到这里均满足无重复字符串
    }
    return maxLen
}

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

image.png

  • “每一字符出现次数都不少于k”,即可使用map,key为字符,value为字符个数。
  • “最长子串”,“子串”即连续,子串可想到滑动窗口,使用两指针,“最长”,即可定义一个变量存储最值,持续更新。
func longestSubstring(s string, k int) int {
    if len(s)==0{
        return 0
    }
    maxLen:=0
    dic:=map[int]int{}
    for i:=0;i<len(s);i++{
        ch:=int(s[i]-'a')
        dic[ch]++
    }
    var splits byte
    for ch,v:=range dic{
        if v>0 && v<k{
            splits=byte(ch)+'a'
            break
        }
    }
    if splits==0{
        return len(s)
    }
    for _,v:=range strings.Split(s,string(splits)){
        maxLen=Max(maxLen,longestSubstring(v,k))
    }
    return maxLen
}
func Max(a,b int)int{
    if a>b{
        return a
    }
    return b
}

  • code 1208

image.png

  • “s的子字符串转化为它在t中对应的子字符串”,“转换”,即判断s和t是否相等,“子字符串”即连续,子串可想到滑动窗口,使用两指针
  • “最大长度”,“最长”,即可定义一个变量存储最值,持续更新。
func equalSubstring(s string, t string, maxCost int) int {
    maxLen:=0
    left:=0
    n:=len(s)
    sum:=0
    for right:=0;right<n;right++{
        diff:=int(s[right])-int(t[right])
        sum=sum+abs(diff)
        for sum>maxCost{
            diff:=int(s[left])-int(t[left])
            sum=sum-abs(diff)
            left++
        }
        maxLen=max(maxLen,right-left+1)
    }
    return maxLen
}

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

func abs(a int)int{
    if a<0{
        return -a
    }
    return a
}
  • code 643
func findMaxAverage(nums []int, k int) float64 {
    var maxValue float64
    var sum float64
    for i:=0;i<k;i++{
        sum=sum+float64(nums[i])
    }
    maxValue=sum/float64(k)
    for i:=0;i<len(nums)-k;i=i+1{
        sum=sum-float64(nums[i])
        sum=sum+float64(nums[i+k])
        maxValue=MaxFloat(maxValue,sum/float64(k))
    }
    return maxValue
}

func MaxFloat(a,b float64)float64{
    if a>b{
        return a
    }
    return b
}
  • code 1423
  • code 1838
func maxFrequency(nums []int, k int) int {
    sort.Ints(nums)
    ans := 1
    for l, r, total := 0, 1, 0; r < len(nums); r++ {
        total += (nums[r] - nums[r-1]) * (r - l)
        for total > k {
            total -= nums[r] - nums[l]
            l++
        }
        ans = max(ans, r-l+1)
    }
    return ans
}

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

  • code 904
func totalFruit(fruits []int) int {
    left:=0
    windows:=map[int]int{}
    maxValue:=0
    for right:=0;right<len(fruits);right++{
        windows[fruits[right]]++
        for len(windows)>2{
            windows[fruits[left]]--
            if windows[fruits[left]]==0{
                delete(windows,fruits[left])
            }
            left++
        }
        maxValue=max(maxValue,right-left+1)
    }
    return maxValue
}

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

  • code 424
func characterReplacement(s string, k int) int {
    maxLen:=0
    windows:=map[byte]int{}
    left:=0
    for right:=0;right<len(s);right++{
        windows[s[right]]++
        if !checkCharacter(windows,k){
            windows[s[left]]--
            left++
        }
        maxLen=Max(maxLen,right-left+1)
    }
    return maxLen
}


func checkCharacter(windows map[byte]int, k int)bool{
    sum:=0
    max:=0
    for _,v:=range windows{
        sum=sum+v
        max=Max(max,v)
    }
    return sum-max<=k
}

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

  • code 1052
func maxSatisfied(customers []int, grumpy []int, minutes int) int {
    res:=0
    for i:=0;i<len(customers);i++{
        if grumpy[i]==0{
            res+=customers[i]
            customers[i]=0
        }
    }
    left:=0
    cur:=0
    maxLen:=0
    for right:=0;right<len(customers);right++{
        cur=cur+customers[right]
        if (right-left+1)>minutes{
            cur=cur-customers[left]
            left++
        }
        maxLen=max(maxLen,cur)
    }
    return res+maxLen
}

  • code 1610
func visiblePoints(points [][]int, angle int, location []int) int {
    sameCnt := 0
    polarDegrees := []float64{}
    for _, p := range points {
        if p[0] == location[0] && p[1] == location[1] {
            sameCnt++
        } else {
            polarDegrees = append(polarDegrees, math.Atan2(float64(p[1]-location[1]), float64(p[0]-location[0])))
        }
    }
    sort.Float64s(polarDegrees)

    n := len(polarDegrees)
    for _, deg := range polarDegrees {
        polarDegrees = append(polarDegrees, deg+2*math.Pi)
    }

    maxCnt := 0
    degree := float64(angle) * math.Pi / 180
    for i, deg := range polarDegrees[:n] {
        j := sort.Search(n*2, func(j int) bool { return polarDegrees[j] > deg+degree })
        if j-i > maxCnt {
            maxCnt = j - i
        }
    }
    return sameCnt + maxCnt
}