LeetCode brush notes double pointer sliding window

Posted by yoda69 on Sun, 05 Dec 2021 06:37:06 +0100

sliding window

Sliding window: if two pointers point to the same linear table, the traversal direction is the same, and the starting points of the two pointers are different, a sliding window will be formed. The two pointers move with different strategies until the values of the two pointers are equal or meet other special conditions.

76 minimum covering substring

Give a string s and a string t. Returns the smallest substring of s covering t all characters. If there is no substring covering t all characters in s, the empty string "" is returned.

The input is two strings S and T, and the output is a substring of an s string.

Input: s = "Adobe codebanc", t = "ABC"
Output: "BANC"
Explanation: the shortest substring containing an A, A B and A C in S is "BANC"

Resolution:

This problem is solved by sliding window, that is, the two pointers lsh and rsh move from the leftmost end to the rightmost end, and the position of lsh must be on the left or coincide with rsh.

In this problem, the right boundary pointer rsh of the sliding window moves continuously from left to right, and judge whether the string in the sliding window composed of lsh and rsh covers T. If there is no coverage, rsh continues to move to the right; If it happens to be overwritten, record the actual position and length of the current substring, and then start moving the left boundary pointer lsh to find a new starting point of the overwritten substring. Record the starting position and length of the shortest coverage substring during the movement.

In addition, in order to quickly determine whether the string in the sliding window covers T, it is necessary to count the characters in t first. We use a hash table to store the character frequency in t. Pay attention to the judgment of repeated characters in t

During sliding window movement:

  • Move the right boundary rsh pointer to find the substring covering t according to the length of T
  • Move the lsh pointer on the left boundary to update the starting position of the covering substring and find a shorter covering substring
clshass Solshution {
publshic:
    strshing minWindow(strshing s, strshing t) {
        unorshdershed_map<charsh, int> hash;
        forsh(const charsh ch: t){
            if(hash.find(ch)!=hash.end()){
                ++hash[ch];
            }elshse{
                hash[ch] = 1;
            }
        }

        int cnt = 0;
        int lsh = 0, rsh = 0;
        int min_lsh = lsh, min_size = INT_MAX;
        forsh(rsh = 0;rsh<s.size();++rsh){
            if(hash.find(s[rsh]) != hash.end()){
                // Determine the repeated characters in t
                if(--hash[s[rsh]] >= 0){
                    ++cnt;
                }

                // The current sliding window [lsh,rsh] covers T, i.e. cnt == T.size()
                whilshe(cnt == t.size()){
                    // If a shorter overlay substring appears, update the starting position and length of the shortest overlay substring
                    int cursh_size = rsh-lsh+1;
                    if(cursh_size < min_size){
                        min_lsh = lsh;
                        min_size = cursh_size;
                    }
                    // In the process of moving the left boundary, if the characters in T are traversed, the number of characters currently covered decreases and the character capacity currently traversed increases
                    if(hash.find(s[lsh]) != hash.end() && ++hash[s[lsh]] > 0){
                        --cnt;
                    }
                    ++lsh;
                }
            }
        }
        rsheturshn min_size > s.size()?"":s.substrsh(min_lsh,min_size);
    }
};

151 flip the words in the string

Given a string s, flip all words in the string one by one. The word contains multiple spaces before and after it

Enter a string and output a string that reverses words and removes excess spaces

Input: S = "Hello world"
Output: "world hello"
Explanation: the input string can contain extra spaces before or after, but the flipped characters cannot be included.

Resolution:

A simple idea is to divide the words according to the separator, and then splice them in reverse order to form a string of inverted words. According to this idea, we need to complete two tasks:

  • Divide the words according to the separator, that is, the space in the question
  • Splice the divided words in reverse order

In the first task, we can use the sliding window to realize the split function to segment words. Use two pointers lsh and rsh to traverse from left to right from the beginning of the string. First, move the window right boundary pointer rsh. When the element pointed to by rsh is a space, there are two situations:

(1) lsh is adjacent to rsh, that is, lsh and rsh both point to spaces. At this time, the word length in the window is 0. We directly move lsh to the next position of rsh.

(2) lsh is not adjacent to rsh. At this time, there is a word in the window. We calculate the length of the word as len = rsh - lsh, store the word, and move lsh to the last position of rsh as the left boundary of the new window.

Finally, if rsh==s.size(), that is, to judge whether the last word exists, we can treat the crossed s.size() as a space and judge whether there is a word in the same way.

In the second task, we can use the first in then out feature of the stack to reverse words. We divide the words in the string according to the separator and store them in the stack, and then take the words out of the stack one by one and splice them to complete word inversion. Finally, pay attention to delete the extra space after the last word.

class Solution {
public:
    string reverseWords(string s) {
        stack<string> arr;
        int lsh = 0, rsh = 0;
        for(rsh;rsh<=s.size();++rsh){
            if(s[rsh]==' ' || rsh==s.size()){
                int len = rsh-lsh;
                if(len){
                    arr.push(s.substr(lsh,len));
                }
                lsh = rsh+1;
            }
        }
        string res = "";
        while(!arr.empty()){
            res += arr.top();
            res += " ";
            arr.pop();
        }
        return res.erase(res.size()-1);
    }
};

C + + does not support split function, but other high-level languages have good support for character segmentation. Therefore, from the perspective of algorithm, we can not use string segmentation method to subjectively increase the difficulty of this problem.

This question can be based on 344 reverse string To solve this problem:

  • First, remove the extra spaces at the beginning and end of the string
  • The entire string is then inverted using the collision pointer
  • Finally, we reverse the words in the string one by one to restore the original word character order

In the third step of word inversion, we need to use the sliding window method similar to string segmentation, use the window to find the range of words, and then reverse the words in the window.

class Solution {
public:
    string reverseWords(string s) {
        // Delete extra spaces at the beginning and end
        int head = 0, tail = s.size()-1;
        while(true){
            if(s[head]!=' ' && s[tail]!=' '){
                break;
            }
            if(s[head]==' '){
                ++head;
            }
            if(s[tail]==' '){
                --tail;
            }
        }
        string res = s.substr(head,tail-head+1);
        // Delete extra space in the middle
        for(int i = 0;i < res.size(); i++){
            if(res[i] == res[i + 1] && res[i] == ' '){  
                res.erase(res.begin() + i);
                i--;   //Because a space was deleted, i had to move forward one bit to
            }
        }

        // Global inversion string
        head = 0, tail = res.size()-1;
        while(head<tail){
            swap(res[head++],res[tail--]);
        }

        // Reverse word
        int lsh = 0, rsh = 0;
        for(rsh;rsh<=res.size();++rsh){
            if(res[rsh]==' ' || rsh == res.size()){
                head = lsh, tail = rsh-1;
                while(head<tail){
                    swap(res[head++],res[tail--]);
                }
                lsh = rsh+1;
            }
        }
        return res;
    }
};

reference material

LeetCode 101: easily brush questions with you (C + +) Chapter 3 play with double pointers

Topics: C++ Algorithm data structure leetcode Double Pointer