[Sliding window] Sliding window template, slide and slide in small algorithm problems

First of all, everyone shouted out our slogan: follow the template, no worries about sliding windows!

1. What is a sliding window?

The sliding window algorithm is a specific algorithm model of the double pointer algorithm, which is often used to find the largest or smallest string, a specific array, and character sequences and other related issues under specific conditions. The purpose of using the sliding window is also very simple. : The problem that originally needs to be solved by double loop nesting is solved by double pointers, so that the time complexity is greatly reduced (generally speaking, the time complexity of O(n^2) is reduced to O(n))

2. The frame and template of the sliding window

The pain points of doing sliding window problems

Many friends may feel this way when brushing LeetCode questions: It seems that this question is solved using a sliding window, how to solve it? Then the two pointers left and right are listed, and then I am at a loss. This is mainly caused by the fact that I am unfamiliar with the execution process of the entire sliding window algorithm. In addition, even if we read the solution, we know how to solve this problem. When we look at this topic again in two days, due to the lack of inspiration for some specific steps of the sliding window algorithm, we are still at a loss for this topic. A summary of the sliding window algorithm, the algorithm model of the sliding window came into being~

Advantages of Using a Sliding Window Framework

The advantages of the sliding window framework can be explained from the following points: 1. Using the sliding window framework can reduce the difficulty of the whole question, and can bring us inspiration in specific difficulties. 2. Using the sliding window framework can make We put more energy into the thinking of the core ideas and improve our efficiency in brushing up questions. 3. Use templates for development. When we look back at this topic, the memory will be directly locked to the difficult points in the topic, and the memory will be more profound.

The frame template of the sliding window is as follows

longest template

The implementation idea of ​​the template is as follows: When we use the template of the sliding window, we give two different implementation ideas and template codes for finding the longest and shortest character sequence or string: the implementation
idea for finding the longest correlation:

The left and right pointers (LR) are at the initial position, and the R pointer gradually slides circularly to the right. During each sliding process, if the elements in the sliding window meet the requirements of the sliding window, the R pointer keeps sliding to the right to expand the window and update it continuously Optimal result; if the elements in the window do not meet the conditions, the L pointer keeps shrinking the window to the right, and the result is continuously updated in the process until R reaches the end

初始化 left,right,result,bestResult
while("右指针没有到结尾"){
    窗口扩大,加入right对应元素,更新当前result
    while("result不满足要求"){
        窗口缩小,移除left对应元素,left右移
    }
    更新最优结果bestResult
    right++;
}
返回bestResult

shortest template

Implementation ideas:

The left and right pointers (LR) are initially at the starting point, and R gradually slides to the right. During each sliding process, if the elements in the window meet the conditions, L shrinks the window to the right and continuously updates the smallest result. If the elements in the window If the condition is not met, R keeps expanding the window to the right until R reaches the end of the string

初始化 left,right,result,bestResult
while("右指针没有到结尾"){
    窗口扩大,加入right对应元素,更新当前result
    while("result满足要求"){
        更新最优结果bestResult
        窗口缩小,移除left对应元素,left右移
    }
    right++;
}
返回bestResult

3. Actual combat analysis

3.1  and the shortest sub-array greater than or equal to target

topic description

problem solving ideas

According to the logic of the template we gave above, we give the following problem-solving ideas: define two pointers (LR), since this question is looking for the shortest sub-array, apply the above template, when the conditions are not met, R keeps Move to the right, when the condition is met, the L pointer moves to the right to continuously reduce the number of elements in the window, and finally obtain the minimum value of the number of arrays sought

sample code

We give example code:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        //设置最小个数
        int count=0;
        int left=0;
        int right=0;
        int sum=0;
        int minLength=Integer.MAX_VALUE;
        //进行遍历
        while(right<nums.length){
            sum+=nums[right];
            count++;
            while(sum>=target){
                if(count<minLength){
                    minLength=count;
                }
                sum-=nums[left];
                 left++;
                count--;
            }
            right++;
        }
        if(minLength==Integer.MAX_VALUE){
            return 0;
        }
        return minLength;
    }
}

3.2  Minimum Covering Substring

topic description

problem solving ideas

Don't be intimidated by the difficulty of this test question, we must always believe: follow the template, and there is no trouble in sliding the window! Ok, let’s talk about our solution to this question: This question is to find the number of substrings required to cover the target substring. We first use a hashmap to compare the characters required by the target substring and the number of characters required by each character. The quantity is traversed, and the two pointers of LR are defined. Since the topic is still to find the minimum substring, when the string we traverse does not meet the requirements, the R pointer traverses to the right continuously, and uses another hashmap to store the elements in the window. When the pointers we have traversed can meet the number of related characters required by the target string, then we will make the L pointer continue to reduce the number of elements in the window to the right, and continue to cycle this process until R reaches the last element of the string

sample code

We give sample code:

class Solution {
    public String minWindow(String s, String t) {
        //创建双指针
        int left=0;
        int right=0;
        //定义两个hashmap
        HashMap<Character,Integer>map1=new HashMap<>();
        HashMap<Character,Integer>map2=new HashMap<>();
        int start=0;
        int len=Integer.MAX_VALUE;
        //设置要求
        int need=0;
        //设置满足情况
        int satisfy=0;
        //遍历要求
        for(char c: t.toCharArray()){
            map1.put(c,map1.getOrDefault(c,0)+1);
            if(map1.get(c)==1){
                need++;
            }
        }
        //进行遍历
        int n=s.length();
        while(right<n){
            map2.put(s.charAt(right),map2.getOrDefault(s.charAt(right),0)+1);
            if(map2.get(s.charAt(right)).equals(map1.get(s.charAt(right)))){
                satisfy++;
            }
            //优化结果
            while(satisfy==need){
                if(len>right-left+1){
                    len=right-left+1;
                    start=left;
                }
                char rm=s.charAt(left);
                if(map1.containsKey(rm)){
                    if(map1.get(rm).equals(map2.get(rm)))
                    satisfy--;
                }
                map2.put(rm,map2.get(rm)-1);
                left++;
            }
            right++;
        }
        if(len==Integer.MAX_VALUE){
            return "";
        }
        return s.substring(start,start+len);
    }
}

3.3  Arrangement of strings

topic description

problem solving ideas

This question is similar to the one above. It also requires two hashmaps. One is used to store standard characters and the number of elements corresponding to each character. It is traversed in the same way as the previous question, and finally there are One difference is that we finally compare the minimum value obtained with the length that meets the requirements, return TRUE if they are equal, and return FALSE if they are not equal

sample code

class Solution {
    public boolean checkInclusion(String s1, String s2) {
        //创建双指针
        int left=0;
        int right=0;
        //创建hashmap
        int[]nums1=new int[26];
        int[]nums2=new int[26];
        int maxLength=Integer.MAX_VALUE;
        int ask=0;
        int satisfy=0;
        //遍历要求
        for(int i=0;i<s1.length();++i){
            nums1[s1.charAt(i)-'a']++;
            if(nums1[s1.charAt(i)-'a']==1){
                ask++;
            }
        }
        //进行遍历
        while(right<s2.length()){
            nums2[s2.charAt(right)-'a']++;
            if(nums2[s2.charAt(right)-'a']==nums1[s2.charAt(right)-'a']){
                satisfy++;
            }
            while(satisfy==ask){
                if(right-left+1<maxLength){
                    maxLength=right-left+1;
                }
                if(nums2[s2.charAt(left)-'a']==(nums1[s2.charAt(left)-'a'])){
                    satisfy--;
                }
                nums2[s2.charAt(left)-'a']--;
                left++;
            }
            right++;
        }
        return maxLength==s1.length()?true:false;
    }
}

3.4  Find all anagrams in a string

topic description

problem solving ideas

It is also a solution similar to the previous question, the only difference is that we count the minLength of each traversal based on the solution of the previous question, and if it meets our requirements, we can directly add this set to the list

sample code

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        //创建list
        List<Integer>list=new ArrayList<>();
        //基本类似的解题思路:
        //创建双指针
        int left=0;
        int right=0;
        //创建两个哈希表
         int[]nums1=new int[26];
        int[]nums2=new int[26];
        int ask=0;
        int satisfy=0;
        //遍历要求
        for(int i=0;i<p.length();++i){
            nums1[p.charAt(i)-'a']++;
            if(nums1[p.charAt(i)-'a']==1){
                ask++;
            }
        }
        //遍历实际的字符串
        while(right<s.length()){
            nums2[s.charAt(right)-'a']++;
            if(nums1[s.charAt(right)-'a']==nums2[s.charAt(right)-'a']){
                satisfy++;
            }
            //优化结果
            while(satisfy==ask){
                if(right-left+1==p.length()){
                    list.add(left);
                }
                if(nums2[s.charAt(left)-'a']==(nums1[s.charAt(left)-'a'])){
                    satisfy--;
                }
                nums2[s.charAt(left)-'a']--;
                left++;
            }
            right++;
        }
        return list;
    }
}

3.5  The longest substring without repeating characters

topic description

problem solving ideas

This question is relatively different from the previous question. From the perspective of the type of sliding window, this is the size of the largest sliding window. Let us describe the problem-solving process of this question in detail: create a hash table to Store the elements we traverse each time, create double pointers to traverse, and the R pointer continues to traverse to the right. Every time an element is traversed, we will add the element to the hash table. When the number of elements in the window does not meet the requirements of the topic (some The element appears twice), then we will move the L pointer to the right continuously until the requirements in the question are met, and finally return our maximum maxLength.

sample code

class Solution {
    public int lengthOfLongestSubstring(String s) {
        
        //创建哈希表
        HashMap<Character,Integer>map=new HashMap<>();
        //定义双指针
        int left=0;
        int right=0;
        //定义总长度
        int n=s.length();
        int maxLength=0;
        while(right<n){
            map.put(s.charAt(right),map.getOrDefault(s.charAt(right),0)+1);
            while(map.get(s.charAt(right))>1){
                 map.put(s.charAt(left),map.get(s.charAt(left))-1);
                 left++;
            }
            if(right-left+1>maxLength){
                maxLength=right-left+1;
            }
            right++;
        }
       return maxLength; 
    }
}

3.6  Maximum Difficulty of the Exam

topic description

problem solving ideas

This problem is also to find the smallest window, and our problem-solving ideas are relatively clear: use the given k universal values ​​to fill the gap between the two parts of TRUE or FALSE, and the R pointer keeps moving to the right. If k cannot satisfy the gap If , L moves to the right until K is satisfied, and traverses until the R pointer traverses to the end of the string

sample code

class Solution {
    public int maxConsecutiveAnswers(String answerKey, int k) {
        //核心思路:使用提供的k的个万能值,来填补TRUE和FALSE之间的空缺值
        //创建两个指针
        int left=0;
        int right=0;
        //创建计数器
        int countT=0;
        int countF=0;
        int n=answerKey.length();
        int maxLength=0;
        //进行遍历循环
        while(right<n){
            char c=answerKey.charAt(right);
            
            if(c=='T'){
                countT++;
            }else{
                countF++;
            }
            //不符合的情况
            while(countT>k&&countF>k){
                char d=answerKey.charAt(left);
                //进行遍历
                if(d=='T'){
                    countT--;
                }else{
                    countF--;
                }
                left++;
            }
            if(right-left+1>maxLength){
                maxLength=right-left+1;
            }
            right++;
        }
        return maxLength;

    }
}

Guess you like

Origin blog.csdn.net/m0_65431718/article/details/130730847
Recommended