编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

滑动窗口:golang实现最小覆盖子串的算法

wxchong 2025-01-19 00:57:44 开源技术 34 ℃ 0 评论

题目介绍:给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。

示例 2:

输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。

解题逻辑还是左右指针,通过他们滑动窗口,不停的缩小窗口来达到目的

以下是我的完整代码:

package main

import (
    "fmt"
    "math"
    "testing"
)

func minWindow(s string, t string) string {
    if len(s) < len(t) {
       return ""
    }

    // 记录 t 中每个字符出现的次数
    targetMap := make(map[byte]int)
    for i := 0; i < len(t); i++ {
       targetMap[t[i]]++
    }

    // 记录窗口中符合要求的字符个数
    formed := 0
    // 记录窗口的左右边界
    left, right := 0, 0
    // 记录最小覆盖子串的起始索引和长度
    ansLeft, ansLen := 0, math.MaxInt32

    // 记录窗口中每个字符出现的次数
    windowMap := make(map[byte]int)

    for right < len(s) {
       // 将字符加入窗口
       c := s[right]
       windowMap[c]++

       // 如果该字符是 t 中的字符且其数量不超过 t 中的要求数量,则 formed++
       if count, ok := targetMap[c]; ok && windowMap[c] <= count {
          formed++
       }

       // 当窗口包含了 t 中的所有字符时,尝试缩小窗口
       for left <= right && formed == len(t) {
          // 更新最小覆盖子串
          if right-left+1 < ansLen {
             ansLeft = left
             ansLen = right - left + 1
          }

          // 移除窗口左边的字符
          c = s[left]
          windowMap[c]--
          // 如果移除的字符是 t 中的字符且其数量小于 t 中的要求数量,则 formed--
          if count, ok := targetMap[c]; ok && windowMap[c] < count {
             formed--
          }

          left++
       }

       right++
    }

    if ansLen == math.MaxInt32 {
       return ""
    }
    return s[ansLeft : ansLeft+ansLen]
}

func TestMinSubString(t *testing.T) {
    s1 := "ADOBECODEBANC"
    t1 := "ABC"
    fmt.Println(minWindow(s1, t1))
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表