[Leetcode] [Tutorial] Sliding window


3. The longest substring without repeated characters

Given a string s, please find the length of the longest substring that does not contain repeated characters.

Example:
Input: s = "pwwkew"
Output: 3
Explanation: Because the longest substring without repeated characters is "wke", its length is 3. Please note that your answer must be the length of the substring, "pwke" is a subsequence, not a substring.

Solution

Using two pointers, instead of moving one bit at a time, it jumps directly to the corresponding position. Form a new window by moving these two pointers.

A dictionary is used in the sliding window to save characters and their indexes. When duplicate characters appear, move the pointer pointing to the left side of the window to remove duplicate characters.

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        left = 0
        max_len = 0
        dic = {
    
    }
        for right, char in enumerate(s):
            if s[right] in dic and dic[s[right]] >= left:
                left = dic[s[right]] + 1
            dic[s[right]] = right
            max_len = max(right - left + 1, max_len)
            right += 1
        return max_len

438. Find all anagrams of letters in a string

Given two strings s and p, find the substrings of all anagrams of p in s and return the starting index of these substrings. The order of answer output is not taken into account.

Allophones refer to strings formed by the rearrangement of the same letters (including identical strings).

Example:
Input: s = “cbaebabacd”, p = “abc”
Output: [0,6]

Solution

Only when the size of the window is equal to the length of the string p, the substring within the window may be an anagram of the string p. In other words, the size of the window is fixed.

We can use a hash table to record the number of each character in the window to quickly determine whether the string in the window is an anagram of p.

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        p_counter = Counter(p)
        res = []

        for i in range(len(p) - 1, len(s)):
            s_counter = Counter(s[i - len(p) + 1: i + 1])
            if s_counter == p_counter:
                res.append(i - len(p) + 1)
        
        return res

It should be noted that Python's slicing operation does not include the terminating index.

However, the time complexity of this algorithm is O(n * m), where n is the length of string s and m is the length of string p, because for every substring of s, we have to calculate its character count .

If you just update the count of new characters in each iteration instead of recalculating the count of characters in the entire window, that is, the sliding window moves one step to the right, new characters enter the window, and old characters leave the window, and only the old and new characters are counted. By increasing or decreasing, the time complexity can be reduced from the previous O(n*m) to O(n), where n is the length of the string s. This is because for each character in s, we only perform constant-time operations.

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        p_counter = Counter(p)
        s_counter = Counter()
        res = []

        for i in range(len(s)):
            s_counter[s[i]] += 1

            if i >= len(p):
                s_counter[s[i - len(p)]] -= 1
            
            if s_counter == p_counter:
                res.append(i - len(p) + 1)

        return res

Guess you like

Origin blog.csdn.net/weixin_45427144/article/details/131312463