← Back to articles

LeetCode — Ling Shen Follow-Along — Sliding Window and Two Pointers — Variable-Length Sliding Window — Longer Is Valid + Shortest + Minimum

Follow-along practice with the variable-length sliding window, discussing the validity condition and how to find the shortest window.

209. Minimum Size Subarray Sum

Problem

Given an array of n positive integers and a positive integer target.

Find the subarray [numsl, numsl+1, …, numsr-1, numsr] in the array whose sum is greater than or equal to target and that has the smallest length, and return its length. If no such subarray exists, return 0.

Example 1:

Input: target = 7, nums = [2,3,1,2,4,3]

Output: 2

Explanation: The subarray [4,3] is the smallest-length subarray under this condition.

Example 2:

Input: target = 4, nums = [1,4,4]

Output: 1

Example 3:

Input: target = 11, nums = [1,1,1,1,1,1,1,1]

Output: 0

Constraints:

1 <= target <= 10^9

1 <= nums.length <= 10^5

1 <= nums[i] <= 10^4

Approach

Use the two-pointer variable-length sliding window idea.

Set a left pointer to control the window size, and use the array index from the loop as the right pointer.

Set a variable that tracks the sum of the numbers in the window.

When the sum meets the requirement:

  • Use a while loop
  • Update the minimum length of the subarray
  • Exclude the value on the left from the window, update the sum, and move the left pointer to the right at the same time
  • End the loop when the sum no longer meets the requirement

Solution

// 209.长度最小的子数组
package main

import (
	"fmt"
	"math"
)

func minSubArrayLen(target int, nums []int) int {
	ans, left := math.MaxInt, 0
	cnt := 0

	for i, num := range nums {
		cnt += num
		for cnt >= target {
			ans = min(ans, i-left+1)
			cnt -= nums[left]
			left += 1
		}
	}

	if ans > len(nums) {
		return 0
	} else {
		return ans
	}
}

func main() {
	testCases := []struct {
		nums   []int
		target int
	}{
		{[]int{2, 3, 1, 2, 4, 3}, 7},
		{[]int{1, 4, 4}, 4},
		{[]int{1, 1, 1, 1, 1, 1, 1, 1}, 11},
	}

	for _, testCase := range testCases {
		fmt.Println(minSubArrayLen(testCase.target, testCase.nums))
	}
}

2904. Shortest and Lexicographically Smallest Beautiful String

Problem

You are given a binary string s and a positive integer k.

If the number of 1s in some substring of s is exactly equal to k, then this substring is called a beautiful substring.

Let len be the length of the shortest beautiful substring.

Return the beautiful substring of length len that is lexicographically smallest. If s contains no beautiful substring, return an empty string.

For two strings a and b of the same length, string a is considered lexicographically greater than string b if at the first position where a and b differ, the character in a at that position is strictly greater than the corresponding character in b.

For example, “abcd” is lexicographically greater than “abcc”, because the first position where the two strings differ is the fourth character, and d is greater than c.

Example 1:

Input: s = “100011001”, k = 3

Output: “11001”

Explanation: There are 7 beautiful substrings in the example:

  1. The substring “100011001”.
  2. The substring “100011001”.
  3. The substring “100011001”.
  4. The substring “100011001”.
  5. The substring “100011001”.
  6. The substring “100011001”.
  7. The substring “100011001”.

The length of the shortest beautiful substring is 5.

The beautiful substring of length 5 that is lexicographically smallest is the substring “11001”.

Example 2:

Input: s = “1011”, k = 2

Output: “11”

Explanation: There are 3 beautiful substrings in the example:

  1. The substring “1011”.
  2. The substring “1011”.
  3. The substring “1011”.

The length of the shortest beautiful substring is 2.

The beautiful substring of length 2 that is lexicographically smallest is the substring “11”.

Example 3:

Input: s = “000”, k = 1

Output: ""

Explanation: There is no beautiful substring in the example.

Constraints:

1 <= s.length <= 100

1 <= k <= s.length

Approach

What we need to do is find a substring in which the number of 1s is k; if there are multiple answers, return the one that is lexicographically smallest.

First, according to the problem, when the number of 1s in the string is less than k, an empty string is returned, so return it directly.

Then initialize the result ans to the input string s, because the worst result is s, so set it to s.

After that, set cnt to the number of 1s in the window and left to the left boundary of the window, and use the loop index as the right boundary.

Each time the right boundary moves:

  • Check whether the number of 1s in the window meets the requirement
  • If it does, start moving the left boundary until the leftmost 1 is excluded
  • In this process there may be many 0s on the left; excluding them shortens the substring, so keep updating the substring and the left boundary, and also pay attention to the case where substrings have the same length, where the lexicographically smallest one must be chosen
  • This process is implemented with a while loop

Solution

// 2904.最短且字典序最小的美丽子字符串
package main

import (
	"fmt"
	"strings"
)

func shortestBeautifulSubstring(s string, k int) string {
	if strings.Count(s, "1") < k {
		return ""
	}
	ans := s
	cnt, left := 0, 0

	for i, ch := range s {
		if ch == '1' {
			cnt += 1
		}

		for cnt >= k {
			tmp := s[left : i+1]
			if s[left] == '1' {
				cnt -= 1
			}
			left += 1
			if len(tmp) == len(ans) {
				if tmp < ans {
					ans = tmp
				}
			}
			if len(tmp) < len(ans) {
				ans = tmp
			}
		}
	}

	return ans
}

func main() {
	testCases := []struct {
		s string
		k int
	}{
		{"100011001", 3},
		{"1011", 2},
		{"000", 1},
	}

	for _, testCase := range testCases {
		fmt.Println(shortestBeautifulSubstring(testCase.s, testCase.k))
	}
}

1234. Replace the Substring for Balanced String

Problem

There is a string of length n that contains only the four characters ‘Q’, ‘W’, ‘E’, and ‘R’.

If in this string these four characters each occur exactly n/4 times, then it is a “balanced string”.

Given such a string s, please make the original string s a “balanced string” by “replacing one substring”.

You may use any other string of the same length as the “substring to be replaced” to perform the replacement.

Please return the minimum possible length of the substring to be replaced.

If the original string is itself a balanced string, return 0.

Example 1:

Input: s = “QWER”

Output: 0

Explanation: s is already balanced.

Example 2:

Input: s = “QQWE”

Output: 1

Explanation: We need to replace one ‘Q’ with ‘R’, so that the resulting “RQWE” (or “QRWE”) is balanced.

Example 3:

Input: s = “QQQW”

Output: 2

Explanation: We can replace the leading “QQ” with “ER”.

Example 4:

Input: s = “QQQQ”

Output: 3

Explanation: We can replace the last 3 ‘Q’s so that s = “QWER”.

Constraints:

1 <= s.length <= 10^5

s.length is a multiple of 4

s contains only the four characters ‘Q’, ‘W’, ‘E’, ‘R’

Approach

Build a minimum window such that the count of each character outside the window is as close to n as possible; this minimum window is the string that needs to be replaced.

Use a hash map to count the number of each character.

Solution

// 1234.替换子串得到平衡字符串
package main

import "fmt"

func balancedString(s string) int {
	// 构建哈希表,统计各自的数量
	// 构建一个最小窗口,让窗口外的每种字符数量尽量接近n,这个最小窗口就是需要替换的字符串
	mp := make(map[byte]int, 4)
	n := len(s) / 4

	for i := 0; i < len(s); i++ {
		mp[s[i]] += 1
	}

	// 已经平衡,返回0
	if mp['Q'] == n && mp['W'] == n && mp['E'] == n && mp['R'] == n {
		return 0
	}

	ans, left := len(s), 0

	for i := 0; i < len(s); i++ {
		mp[s[i]] -= 1 // 放进窗口
		for mp['Q'] <= n && mp['W'] <= n && mp['E'] <= n && mp['R'] <= n {
			// 满足条件,记录并收缩
			ans = min(ans, i-left+1)
			mp[s[left]] += 1
			left += 1
		}
	}

	return ans
}

func main() {
	testCases := []string{
		"QWER",
		"QQWE",
		"QQQW",
		"QQQQ",
	}

	for _, testCase := range testCases {
		fmt.Println(balancedString(testCase))
	}
}

2875. Minimum Size Subarray in Infinite Array

Problem

You are given a 0-indexed array nums and an integer target.

The 0-indexed array infinite_nums is generated by infinitely appending the elements of nums to itself.

Find the shortest subarray of infinite_nums whose element sum equals target, and return the length of that subarray. If no subarray satisfying the condition exists, return -1.

Example 1:

Input: nums = [1,2,3], target = 5

Output: 2

Explanation: In this example, infinite_nums = [1,2,3,1,2,3,1,2,…].

The subarray within the interval [1,2] has an element sum equal to target = 5, and the length is 2.

It can be shown that when the element sum equals the target value target = 5, 2 is the shortest length of a subarray.

Example 2:

Input: nums = [1,1,1,2,3], target = 4

Output: 2

Explanation: In this example, infinite_nums = [1,1,1,2,3,1,1,1,2,3,1,1,…].

The subarray within the interval [4,5] has an element sum equal to target = 4, and the length is 2.

It can be shown that when the element sum equals the target value target = 4, 2 is the shortest length of a subarray.

Example 3:

Input: nums = [2,4,6,8], target = 3

Output: -1

Explanation: In this example, infinite_nums = [2,4,6,8,2,4,6,8,…].

It can be shown that there is no subarray whose element sum equals the target value target = 3.

Constraints:

1 <= nums.length <= 10^5

1 <= nums[i] <= 10^5

1 <= target <= 10^9

Approach

The number of nums used is not fixed; it may be 1 to n, but it can be observed that if n are used, the middle n-2 are complete, and for the left nums and right nums, we take consecutive data from the right and from the left respectively.

Let the sum of the data in nums be total.

target = total*m + res

res = nums*2[i:j]

What we need to do is find the length of res.

res = target & total

Everything else can be done following the same fixed steps.

Solution

// 2875.无限数组的最短子数组
package main

import (
	"fmt"
	"math"
)

func minSizeSubarray(nums []int, target int) int {
	total := 0
	for _, x := range nums {
		total += x
	}

	ans := math.MaxInt
	left, sum, n := 0, 0, len(nums)
	for right := 0; right < n*2; right++ {
		sum += nums[right%n]
		for sum > target%total {
			sum -= nums[left%n]
			left++
		}
		if sum == target%total {
			ans = min(ans, right-left+1)
		}
	}
	if ans == math.MaxInt {
		return -1
	}
	return ans + target/total*n
}

func main() {
	testCases := []struct {
		nums   []int
		target int
	}{
		{[]int{1, 2, 3}, 5},
		{[]int{1, 1, 1, 2, 3}, 4},
		{[]int{2, 4, 6, 8}, 3},
	}

	for _, testCase := range testCases {
		fmt.Println(minSizeSubarray(testCase.nums, testCase.target))
	}
}

76. Minimum Window Substring

Problem

Given a string s and a string t, return the minimum substring of s that covers all the characters of t. If there is no substring in s that covers all the characters of t, return the empty string "".

Note:

For duplicate characters in t, the number of that character in the substring we are looking for must be no less than the number of that character in t.

If such a substring exists in s, we guarantee that it is the only answer.

Example 1:

Input: s = “ADOBECODEBANC”, t = “ABC”

Output: “BANC”

Explanation: The minimum covering substring “BANC” contains ‘A’, ‘B’, and ‘C’ from string t.

Example 2:

Input: s = “a”, t = “a”

Output: “a”

Explanation: The entire string s is the minimum covering substring.

Example 3:

Input: s = “a”, t = “aa”

Output: ""

Explanation: Both characters ‘a’ in t should be included in a substring of s, so there is no substring satisfying the condition, and the empty string is returned.

Constraints:

m == s.length

n == t.length

1 <= m, n <= 10^5

s and t consist of English letters.

Approach

First, the problem asks us to find a substring of s that contains all the characters in t (both the distinct characters and their counts).

First, we need to know which characters are in t.

Then, find a substring in s that contains all kinds of characters in t, and make this substring as small as possible.

So use a hash map to count all the kinds and counts of characters in t.

Then look for a substring in s: if a character in the substring is in the hash map, subtract it; if all the counts in the hash map become 0, it means the substring already contains all the characters in t, then shrink the window until it no longer meets the requirement.

Solution

// 76.最小覆盖子串
package main

import (
	"fmt"
	"math"
)

func minWindow(s string, t string) string {
	// 先统计一下t中各个字符的数量,统计一下字符的种类
	mp := make(map[byte]int)

	for i := 0; i < len(t); i++ {
		mp[t[i]] += 1
	}
	left := 0
	cnt := len(mp) // 字符的种类
	ans := ""
	tmp := math.MaxInt

	for i := 0; i < len(s); i++ {
		if _, ok := mp[s[i]]; ok { // 字符有效
			mp[s[i]] -= 1
			if mp[s[i]] == 0 { // 符合要求
				cnt -= 1
			}
		}

		for cnt == 0 { // 子串中已经满足要求,缩小子串范围
			if tmp > i-left+1 {
				tmp = i - left + 1
				ans = s[left : i+1]
			}
			if _, ok := mp[s[left]]; ok { // 字符有效
				mp[s[left]] += 1
				if mp[s[left]] == 1 { // 符合要求
					cnt += 1
				}
			}
			left += 1
		}
	}

	return ans
}

func main() {
	testCases := []struct {
		s string
		t string
	}{
		{"ADOBECODEBANC", "ABC"},
		{"a", "a"},
		{"a", "aa"},
	}

	for _, testCase := range testCases {
		fmt.Println(minWindow(testCase.s, testCase.t))
	}
}

632. Smallest Range Covering Elements from K Lists

Problem

You have k lists of integers sorted in non-decreasing order. Find the smallest range such that each of the k lists has at least one number contained in it.

We define range [a,b] as smaller than range [c,d] if b-a < d-c, or if b-a == d-c then a < c.

Example 1:

Input: nums = [[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]

Output: [20,24]

Explanation:

List 1: [4, 10, 15, 24, 26], 24 is in range [20,24].

List 2: [0, 9, 12, 20], 20 is in range [20,24].

List 3: [5, 18, 22, 30], 22 is in range [20,24].

Example 2:

Input: nums = [[1,2,3],[1,2,3],[1,2,3]]

Output: [1,1]

Constraints:

nums.length == k

1 <= k <= 3500

1 <= nums[i].length <= 50

-105 <= nums[i][j] <= 10^5

nums[i] is sorted in non-decreasing order

Approach

Build pairs containing the number and its position, then sort them, and build a sliding window that covers all indices and is as small as possible.

Solution

// 632.最小区间
package main

import (
	"fmt"
	"slices"
)

func smallestRange(nums [][]int) []int {
	type pair struct{ x, i int } // 数字和他们所在的位置
	pairs := []pair{}

	for i, arr := range nums {
		for _, num := range arr {
			pairs = append(pairs, pair{num, i})
		}
	}

	slices.SortFunc(pairs, func(a, b pair) int { return a.x - b.x })

	ansL, ansR := pairs[0].x, pairs[len(pairs)-1].x
	mp := make(map[int]int)
	left := 0

	for _, p := range pairs {
		r, i := p.x, p.i
		mp[i] += 1

		for len(mp) == len(nums) { // 每个列表都至少包含一个数
			l, i := pairs[left].x, pairs[left].i
			if r-l < ansR-ansL {
				ansL, ansR = l, r
			}
			mp[i] -= 1
			if mp[i] == 0 {
				delete(mp, i)
			}
			left += 1
		}
	}
	return []int{ansL, ansR}
}

func main() {
	testCases := [][][]int{
		[][]int{
			[]int{4, 10, 15, 24, 26},
			[]int{0, 9, 12, 20},
			[]int{5, 18, 22, 30},
		},
		[][]int{
			[]int{1, 2, 3},
			[]int{1, 2, 3},
			[]int{1, 2, 3},
		},
	}

	for _, testCase := range testCases {
		fmt.Println(smallestRange(testCase))
	}
}
About this article’s date

Kept from the date marked on the original article at the old site; the actual date writing began may be earlier.

Original date: 2025-11-16 17:00:16 +0800

In this series · Sliding windows and two pointers

PreviousLeetCode Follow-Along with Ling: Sliding Window and Two Pointers — Fixed-Length Sliding Window: Basics ←