# leetcode lecture on algorithm interview in Dachang 8. Sliding window

## leetcode lecture on algorithm interview in Dachang 8. Sliding window

#### catalog:

1. Introduction

2. Time and space complexity

3. Dynamic planning

4. Greed

5. Binary search

6. Depth first & breadth first

7. Double pointer

8. Sliding window

9. Bit operation

10. Recursion & divide and conquer

11 Pruning & backtracking

12. Reactor

13. Monotone stack

14. Sorting algorithm

16.set&map

17. Stack

18. Queue

19. Array

20. String

21. Trees

22. Dictionary tree

23. Consolidation

24. Other types of questions

#### 3. Longest substring without repeated characters (medium)

##### Method 1. Sliding window

The animation is too large. Click to view it

• Idea: the sliding window keeps moving forward. If the current element is not in the set, add the set, and then update the maximum length. i + + continues the next cycle. If there are duplicate elements in the set, keep j + + and delete the elements outside the window until there are no duplicate elements in the sliding window
• Complexity: time complexity O(n), n is the length of the string. The space complexity is O(n), that is, the space of set, and the worst case is O(n)

js:

```var lengthOfLongestSubstring = function (s) {
const set = new Set(); //Determine whether there are duplicate elements in the sliding window
let i = 0,//Sliding window right border
j = 0,//Sliding window left border
maxLength = 0;
if (s.length === 0) {//Extreme situation
return 0;
}
for (i; i < s.length; i++) {
if (!set.has(s[i])) {//If the current element is not in set, add set, and then update the maximum length. i + + continues the next cycle
maxLength = Math.max(maxLength, set.size);
} else {
//There are duplicate elements in set. Keep j + + and delete the elements outside the window until there are no duplicate elements in the sliding window
while (set.has(s[i])) {
set Sliding window traverses the string and keeps changing.delete(s[j]);
j++;
}
}
}
return maxLength;
};
```

Java:

```class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> set = new HashSet<Character>();
int n = s.length();
int j = -1, ans = 0;
for (int i = 0; i < n; ++i) {
if (i != 0) {
set.remove(s.charAt(i - 1));
}
while (j + 1 < n && !set.contains(s.charAt(j + 1))) {
++j;
}
ans = Math.max(ans, j - i + 1);
}
return ans;
}
}
```

#### 219. Duplicate Element II exists (easy)

The animation is too large. Click to view it

##### Method 1: sliding window
• Idea: loop the array, and constantly add elements to the sliding window, that is, add set. If there are duplicate elements in the set and the window size is less than the specified size, return. Otherwise, add it to the set. When the sliding window exceeds the specified size, reduce the window
• Complexity: time complexity O(n), space complexity O(min(n, k))

js:

```var containsNearbyDuplicate = function(nums, k) {
const set = new Set();
for(let i = 0; i < nums.length; i++) {
if(set.has(nums[i])) {//Duplicate element found
return true;
}
if(set.size > k) {//The sliding window exceeds the specified size. Reduce the window
set.delete(nums[i - k]);
}
}
return false;
};
```

java:

```class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
HashSet<Integer> set = new HashSet<>();
for(int i = 0; i < nums.length; i++) {
if(set.contains(nums[i])) {
return true;
}
if(set.size() > k) {
set.remove(nums[i - k]);
}
}
return false;
}
}

```

#### 76. Minimum coverage substring (hard)

##### Method 1. Sliding window
• Idea: use the left and right pointers to traverse the s string. When the characters in the sliding window cannot cover the characters in T, move the right pointer to the right, expand the window, and add the characters on the right to the sliding window. When the characters in the sliding window can cover the characters in t, keep moving the left pointer to the left and narrow the window until the characters in the window just cover the characters in t, At this time, the characters in t cannot be overwritten when moving to the left. During the movement of the pointer, the minimum covering substring is constantly updated
• Complexity: time complexity o(n), n is the length of s, space complexity o(t), t is the size of character set

The animation is too large. Click to view it

js:

```var minWindow = function (s, t) {
let need = {};//Frequency of strings to be overwritten
let window = {};//String frequency of sliding window
for (let a of t) {
need[a] = (need[a] || 0) + 1;//Count the frequency of characters in t
}
//Left and right pointer
let left = 0,
right = 0;
let valid = 0;//The number of character types that can be covered in the sliding window
let start = 0,//Starting cable of minimum covering substring
len = Number.MAX_VALUE;//Minimum covering substring length
while (right < s.length) {
let c = s[right];//Enter the character on the right of the sliding window
right++;//Move window right
if (need[c]) {//If the current character is in the need character, update the number of characters in the window
window[c] = (window[c] || 0) + 1;
if (window[c] == need[c]) {//If the current window and the required number of characters are the same, the character type + 1
valid++;
}
}

while (valid == Object.keys(need).length) {//When the character type is consistent with the required number of characters, the window will be narrowed
if (right - left < len) {//The length of the current window is less than the length of the previous window. len updates the starting position and length of the minimum coverage substring
start = left;
len = right - left;
}
let d = s[left];//Characters to be removed
left++;//Move window left removes characters from the window
if (need[d]) {//If the number of characters in the window is updated in the required characters
if (window[d] == need[d]) {//If the current window is consistent with the required number of characters, the character type is - 1
valid--;
}
window[d]--;
}
}
}
//The override substring '' was not found, otherwise the override substring will be returned
return len == Number.MAX_VALUE ? "" : s.substr(start, len);
};

```

Java:

```class Solution {
public String minWindow(String s, String t) {
Map<Character,Integer> needMap = new HashMap<Character,Integer>();
Map<Character,Integer> windowsMap = new HashMap<Character,Integer>();
for(char c : t.toCharArray()){
needMap.put(c,needMap.getOrDefault(c,0)+1);
}
int left = 0,right = 0;
int valid = 0;
int start = 0,end = 0,len = Integer.MAX_VALUE;
while(right < s.length()){
char c = s.charAt(right);
right++;
if(needMap.containsKey(c)){
windowsMap.put(c,windowsMap.getOrDefault(c,0)+1);
if(windowsMap.get(c).equals(needMap.get(c))){
valid++;
}
}
while(valid == needMap.size()){
if(right - left< len){
len = right - left;
start = left;
}
char d = s.charAt(left);
left++;
if(windowsMap.containsKey(d)){
if(windowsMap.get(d).equals(needMap.get(d))){
valid--;
}
windowsMap.put(d,windowsMap.getOrDefault(d,0)-1);
}
}
}
return len == Integer.MAX_VALUE ? "" : s.substring(start,start+len);
}
}
```

#### 438. Find all letter words in the string (medium)

The animation is too large. Click to view it

• Idea: use the idea of sliding window to traverse the string,
1. Judge whether the character entering the window is the required character, and whether the number of characters after adding the window is consistent with the number of characters in need
2. Judge whether the characters in the window are the required characters, and whether the number of characters in the window is consistent with the number of characters in need
3. Judge whether the characters that meet the requirements in the window and need are consistent. If they are consistent, the substring formed by this window is an ectopic word
• Complexity: time complexity O(n), n is the length of the string. Space complexity O(k), K is the space of the character set

js:

```//Writing method 1
var findAnagrams = function (s, p) {
let need = {};//Required characters
let win = {};//Characters in the window
for (let a of p) {//Count the number of ectopic words
need[a] = (need[a] || 0) + 1;
}
//Left and right pointer
let left = 0,
right = 0;
let val = 0;//The character type with the same number of characters in the window and need
let res = [];
while (right < s.length) {
let c = s[right];
right++;//The character on the right enters the window
if (need[c]) {
win[c] = (win[c] || 0) + 1;//If the current character is in need, update the number of characters in the window
if (win[c] == need[c]) {
val++;//When the character matches the character in need in the window, the character type + 1
}
}
while (right - left >= p.length) {//Keep coming out of the window
if (val == Object.keys(need).length) {//If the substring and p in the window are ectopic words, add the left boundary to res
res.push(left);
}
let d = s[left];
left++;//Out window
if (need[d]) {//If the character is in need, update the number and type of characters in the window
if (win[d] == need[d]) {
val--;
}
win[d]--;
}
}
}
return res;
};

//Writing method 2
var findAnagrams = function (s, p) {
//res: returned result
//win: store the characters in the window and the corresponding frequency
//need: the type and number of ectopic words needed for storage
//len: character type of need ectopic word
//val: the character type with the same number of characters in the sliding window and need
const res = [], win = {}, need = {}, pLen = p.length;
let len = 0, val = 0;
for (const x of p) {//Cycle p
//If the character does not exist in need, initialize the number of corresponding characters in the need array and add 1 to the character type
if (need[x] === undefined) {
need[x] = win[x] = 0;
len++;
}
need[x]++;//If the character exists in need, the number of characters is increased by 1
}
for (let i = 0; i < s.length; i++) {
const j = i - pLen;//Sliding window left border
//If the character s[i] entering the sliding window is in need, and the number of characters in the window plus 1 is the same as that in need,
//It indicates that the character has met the requirements of ectopic characters. Let val add 1
if (s[i] in need && ++win[s[i]] === need[s[i]]) val++;
//If the character s[j] of the sliding window is in need, and the number of characters in the sliding window is the same as that in need,
//Note: after removing the character from the window, the requirements for ectopic characters are not met. Reduce the number of characters in the window by 1 and val by 1
if (s[j] in need && win[s[j]]-- === need[s[j]]) val--;
//If the types of ectopic characters in the sliding window in need are the same, it means that starting from j+1 is a starting point of ectopic string
if (val === len) res.push(j + 1);
}
return res;
};

```

java:

```class Solution {
public List<Integer> findAnagrams(String s, String p) {
int[] need = new int;
for (int i = 0; i < p.length(); i++) {
need[p.charAt(i) - 'a']++;
}
int start = 0, end = 0;
int[] window = new int;
List<Integer> ans = new ArrayList<Integer>();
while (end < s.length()) {
window[s.charAt(end) - 'a']++;
if (end - start + 1 == p.length()) {
window[s.charAt(start) - 'a']--;
start++;
}
end++;
}
return ans;
}
}
```

#### 1456. Maximum number of vowels in a fixed length substring (medium) • Idea: slide the window to traverse the string and constantly update the maximum number of vowels
• Complexity: time complexity O(n), where n is the length of the string. Space complexity O(1)

js:

```//Example: s=leetcode k=3
var maxVowels = function (s, k) {
const vowels = new Set(['a', 'e', 'i', 'o', 'u'])
let count = 0,
l = 0,
r = 0
while (r < k) {//Initialize window size k
vowels.has(s[r]) && count++
r++
}
let max = count
while (r < s.length) {//Keep moving windows
vowels.has(s[r]) && count++
vowels.has(s[l]) && count--
l++
r++
max = Math.max(max, count)//Update maximum vowels
}
return max
};

```

java:

```class Solution {
public int maxVowels(String s, int k) {
int n = s.length();
int count = 0;
for (int i = 0; i < k; ++i) {
count += isVowel(s.charAt(i));
}
int ans = count;
for (int i = k; i < n; ++i) {
count += isVowel(s.charAt(i)) - isVowel(s.charAt(i - k));
ans = Math.max(ans, count);
}
return ans;
}

public int isVowel(char ch) {
return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' ? 1 : 0;
}
}

```

The animation is too large. Click to view it

• Idea: use the sliding window to traverse fruits. When a new kind of fruit enters the window
1. If there is only one fruit in the window, add the fruit to the arr array
2. If there are two kinds of fruits, update the left boundary of the window and update the types of fruits in the arr
3. If a new type of fruit comes in, update the location of the previous fruit
4. Update the maximum value of the sliding window
• Complexity: time complexity O(n), space complexity O(1).

js:

```//[1,1,2,2]
//[1,1,2,2,3] -> [2,2,3]
var totalFruit = function(fruits) {
let l = 0;//Start pointer
let maxLen = 0;//The maximum length of the window, which contains up to two kinds of fruits
let n = 0//End position of the former fruit
let arr = [fruits[l]]//Type array of fruit

for(let r = 0; r < fruits.length; r++){//The right pointer of the window keeps moving forward
if(!arr.includes(fruits[r])){//If the window does not contain the fruit in the window
if(arr.length <= 1){//If there is only one fruit
arr = fruits[r]//Add this fruit to the arr array
}else{//If there are two kinds of fruit
l = n//Update the left border of the window
arr = fruits[r-1]//Update the types of fruits in arr
arr = fruits[r]
}
}

if(fruits[r] !== fruits[n]){//If a new type of fruit comes in, update the location of the previous fruit
n = r
}

maxLen = Math.max(maxLen,r-l+1)//Update the maximum value of the sliding window
}
return maxLen

};

```

java:

```class Solution {
public int totalFruit(int[] tree) {
if (tree == null || tree.length == 0) return 0;
int n = tree.length;

Map<Integer, Integer> map = new HashMap<>();
int maxLen = 0, left = 0;
for (int i = 0; i < n; i++) {
map.put(tree[i], map.getOrDefault(tree[i], 0) + 1);
while (map.size() > 2) {
map.put(tree[left], map.get(tree[left]) - 1);
if (map.get(tree[left]) == 0) map.remove(tree[left]);
left++;
}
maxLen = Math.max(maxLen, i - left + 1);
}
return maxLen;
}
}

```

Posted on Fri, 26 Nov 2021 21:57:23 -0500 by voyde