题目:
str:="XDOYEZODEYXNZ"
str1:="XYZ"
两个字符串,返回str包含str
的最小长度为4
分析:
滑动窗口问题
1,设置窗口,left和right为窗口的左右指针,为了满足条件,(将所有str的字符包含住)窗口需要先右移,(left不动,right++),满足条件后,右指针停住。开始进入步骤2,(用map记录str的字符,key为字符,value为字符个数,用一个数all记住需要包含的总个数,包含住一个,all-1,对应的value-1,当value为负数,说明这个字符多出来了,all不变)
2,右指针不变,左指针向右移动,缩小窗口以确定最小的区间,(left指针右移时,遇到value值小于0的字符,value++,一直到value>=0,allcai ++)当左指针左移到不满足条件时,(all>0,包不住str了),左指针停止,进入步骤1右指针开始右移,
循环上述步骤,直到字符串结尾
代码:
package main
import(
"fmt"
"math"
)
func process1(str,str1 string) {
value:=make(map[string]int)
for _,v:=range(str1){
value[string(v)]+=1
}
all:=0
for _,v :=range(value){
all+=v
}
fmt.Println(value,all)
min:=math.MaxUint16
L:=0
R:=0
for R!=len(str) {
//不满足条件,没有捕获所有子串的时候,窗口右移直到捕获所有子串字符
if _,ok:=value[string(str[R])];ok{
value[string(str[R])]--//移动右指针,当右指针指向的字符str[R]在map,值减去1
if value[string(str[R])]>=0{//当all的值大于等于0在将all减去1
all--
}
fmt.Printf("右移 %v %v 减去 %v map=%v all=%v \n",R,string(str[R]),1,value,all)
}//此时map中的值要么为0(刚好包含),要么是负值(有多余)
//all==0说明经过右移之后已经捕获了所有子串字符,接下来就把左指针左移,看看窗口能否缩小
if all==0{//all=0时开始移动左指针
fmt.Printf("all==0 and %v %v %v \n",L,R,value)
for L<R {//
if _,ok:=value[string(str[L])];ok{//如果在map
fmt.Printf("ok %v\n",string(str[L]))
fmt.Printf("左移 %v %v 加上 %v map=%v all=%v \n",L,string(str[L]),1,value,all)
if value[string(str[L])]<0{//如果在map中的值小于0,++,all不变
value[string(str[L])]++
fmt.Printf("小于 %v all= %v \n",value,all)
fmt.Println(L,R)
}else{
all++//str[L]的值不小于0,value++, all++,此时all大于0,说明窗口不满足条件了,要右移捕获更多字符
value[string(str[L])]++
fmt.Printf("大于 %v all= %v \n",value,all)
// min=int(math.Min(float64(min),float64(R-L+1)))//拿到最小值
L++
break
}
}
L++
}
fmt.Println(L,R)
min=int(math.Min(float64(min),float64(R-L+2)))//拿到最小值
fmt.Printf("second min innnnn %v\n",min)
}
R++
}
fmt.Println(min)
}
func main(){
// str:="bbcabccab"
// str1:="abc"
str:="XDOYEZODEYXNZ"
str1:="XYZ"
process1(str,str1)
}
在这里插入代码片