Границы
left := 0
for right, value := range nums {
add(value)
for windowIsInvalid() {
remove(nums[left])
left++
}
}
Каждый элемент входит и выходит из окна не более одного раза.
Окно поддерживает состояние непрерывного подмассива или подстроки без повторного пересчёта.
Минимальный синтаксис, который понадобится в решении.
left := 0
for right, value := range nums {
add(value)
for windowIsInvalid() {
remove(nums[left])
left++
}
}
Каждый элемент входит и выходит из окна не более одного раза.
count := make(map[byte]int)
count[s[right]]++
count[s[left]]--
Map или фиксированный [128]int хранит состояние окна.
sum += nums[right]
if right >= k { sum -= nums[right-k] }
if right >= k-1 { best = max(best, sum) }
Сумма обновляется за O(1), а не пересчитывается за O(k).
Три идиоматичных решения на Go с оценкой времени и памяти.
Left прыгает за последнее вхождение символа.
O(n) time · O(alphabet) spacefunc lengthOfLongestSubstring(s string) int {
last := map[byte]int{}
left, best := 0, 0
for right := range s {
if pos, ok := last[s[right]]; ok && pos >= left {
left = pos + 1
}
last[s[right]] = right
best = max(best, right-left+1)
}
return best
}
Сжимаем окно, пока сумма достаточна.
O(n) time · O(1) spacefunc minSubArrayLen(target int, nums []int) int {
left, sum, answer := 0, 0, len(nums)+1
for right, n := range nums {
sum += n
for sum >= target {
answer = min(answer, right-left+1)
sum -= nums[left]
left++
}
}
if answer > len(nums) { return 0 }
return answer
}
Фиксированное окно сравниваем по частотам.
O(n) time · O(1) spacefunc checkInclusion(pattern, s string) bool {
var need, have [26]int
for i := range pattern { need[pattern[i]-'a']++ }
for right := range s {
have[s[right]-'a']++
if right >= len(pattern) { have[s[right-len(pattern)]-'a']-- }
if have == need { return true }
}
return false
}