leetcode刷题笔记七十六题 最小覆盖子串
源地址:76. 最小覆盖子串
问题描述:
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
说明:如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
/**
本题为典型的滑动窗口问题
此类问题的基本模板是:
while(right < rightEdge){
将right内容加入滑动窗口
right++
windowLen++
while(窗口内内容满足要求){
更新窗口start位置与长度
将窗口左侧元素移除窗口
left--
}
}
*/
import scala.collection.mutable
object Solution {
def minWindow(s: String, t: String): String = {
if (s.length < t.length) return ""
/**
needs: 需求映射,本题中为t的组成映射
windows: 窗口内映射
left: 窗口左端
right: 窗口右端
vaild: 窗口满足条件
start: 满足条件开始位置
len: 满足条件的长度
*/
val needs = mutable.Map[Char, Int]()
val windows = mutable.Map[Char, Int]()
var left = 0
var right = 0
var vaild = 0
var start = 0
var len = Int.MaxValue
t.foreach(c => needs(c) = needs.getOrElse(c, 0) + 1)
while(right < s.length){
val tempChar = s(right)
right += 1
//当右侧元素出现在needs中时,将其加入windows
//如果此时windows中关于tempChar满足needs要求,vaild更新
if(needs.contains(tempChar)){
windows(tempChar) = windows.getOrElse(tempChar, 0) + 1
if(windows(tempChar) == needs(tempChar)) vaild += 1
}
//vaild只有windows全部满足needs要求的情况下,才能和needs.size相等
while(vaild == needs.size){
//更新start len
if(right - left < len){
start = left
len = right - left
}
val backChar = s(left)
left += 1
//取出左侧元素,需要注意的是,左侧元素移除条件为windows中移除该元素后仍满足要求,以本题为例防止出现ABCCB的情况
if(needs.contains(backChar)){
if(windows(backChar) >= needs(backChar)){
windows(backChar) -= 1
//去除后不满足要求 更新vaild 退出左移
if(windows(backChar) < needs(backChar)) vaild -= 1
}
}
}
}
if(len == Int.MaxValue) return ""
else return s.substring(start, start+len)
}
}