3无重复字符的最长子串,567 字符串的排列
无重复字符的最长子串
滑动窗口/双指针
func max(a,b int)int{
if a<b{
return b
}
return a
}
func lengthOfLongestSubstring(s string) int {
m:=map[byte]int{}
n:=len(s)
ans,right:=0,-1
for left:=0;left<n;left++{
//左指针右移时,删除前个左指针对应的字符
if left!=0{
delete(m,s[left-1])
}
//下一个字符没到结尾且没有重复
for right+1<n&&m[s[right+1]]==0{
m[s[right+1]]++
right++
}
//确定长度,若当前子串长度更长,则替换
ans=max(ans,right-left+1)
}
return ans
}
字符串的排列
滑动窗口,设置窗口值为len(s1),因为不考虑顺序,问题为判断S2是否包含S1的排列,因此只需窗口中字符串含有的字符和s1字符相等即可
func checkInclusion(s1 string, s2 string) bool {
//如果s1长度大于s2,必然不包含
if len(s1)>len(s2){
return false
}
var cnt1,cnt2 [26]int
//初始化cnt1为s1的字符串字符统计,cnt2为s1第一个子串(前len(s1)个字符)
for i,v:=range s1{
cnt1[v-'a']++
cnt2[s2[i]-'a']++
}
//cnt1和cnt2初始时是否相同
if cnt1==cnt2{
return true
}
//移动窗口
for j:=len(s1);j<len(s2);j++{
cnt2[s2[j]-'a']++
cnt2[s2[j-len(s1)]-'a']--
if cnt1==cnt2{
return true
}
}
return false
}
双指针,
- s1的所有元素必定在s2中,所以 s1 长度需要大于 s2 。
- 将 s1 的的元素存放在 cnt数组中(已长度26表示26个小写字母)。每有一个元素,值减一。这是为了在后面双指针方法遍历 s2 的时候,每个元素 count数为0时,才说明刚好双指针范围内符合连续条件;如果 count >0, 那么会将之前左指针向右移动
- 判断左右指针里数据长度是否跟 s1 长度一致,是即为结果。
func checkInclusion(s1, s2 string) bool {
n, m := len(s1), len(s2)
if n > m {
return false
}
cnt := [26]int{}
for _, ch := range s1 {
cnt[ch-'a']--
}
left := 0
for right, ch := range s2 {
x := ch - 'a'
cnt[x]++
for cnt[x] > 0 {
cnt[s2[left]-'a']--
left++
}
if right-left+1 == n {
return true
}
}
return false
}
来源:力扣(LeetCode)