[Leetcode Brush Questions-Python/C++] Minimum length subarray (sliding window)

209. Minimum Length Subarray

209. Minimum Length Subarray

topic

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

Find the smallest continuous subarray [numsl, numsl+1, …, numsr-1, numsr] whose sum ≥ target satisfies the array, and return its length. Returns 0 if no matching subarray exists.

Input: target = 7, nums = [2,3,1,2,4,3]
Output: 2
Explanation: The subarray [4,3] is the subarray with the smallest length under this condition.

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

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

the code

class Solution(object):
    def minSubArrayLen(self, target, nums):
        """
        :type target: int
        :type nums: List[int]
        :rtype: int
        """
        res=float("inf")# 定义一个无限大的数
        Sum=0    
        i=0     
        for j in range(len(nums)):
            Sum+=nums[j]
            while Sum>=target:
                res=min(res, j-i+1)
                Sum-=nums[i]
                i+=1
        if res == float("inf"):
            return 0
        else:
            return res
        #return 0 if res == float("inf") else res
class Solution {
    
    
public:
    int minSubArrayLen(int s, vector<int>& nums) {
    
    
        int result = INT32_MAX;
        int sum = 0; // 滑动窗口数值之和
        int i = 0; // 滑动窗口起始位置
        int subLength = 0; // 滑动窗口的长度
        for (int j = 0; j < nums.size(); j++) {
    
    
            sum += nums[j];
            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
            while (sum >= s) {
    
    
                subLength = (j - i + 1); // 取子序列的长度
                result = result < subLength ? result : subLength;
                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == INT32_MAX ? 0 : result;
    }
};

Summarize

  • sliding window
  • Double pointer, the calculation result of the first half can continue to use Sum-=nums[i]

904. Fruit Basket

904. Fruit Basket

topic

You are visiting a farm with a row of fruit trees planted from left to right. These trees are represented by an integer array fruits, where fruits[i] is the fruit type on the i-th tree.

You want to collect as many fruits as possible. However, the owner of the farm has set some strict rules that you must follow to pick the fruit:

  • You only have two baskets, and each basket can only hold a single type of fruit. There is no limit to the total amount of fruit each basket can hold.
  • You can choose any tree to start picking, and you must pick exactly one fruit from each tree (including the tree you started picking). Fruit picked should match the type of fruit in the basket. Each time you pick, you will move right to the next tree and continue picking.
  • Once you get to a tree and the fruit doesn't fit the type of fruit in your basket, then you have to stop picking.

Given an integer array fruits, return the maximum number of fruits you can collect.

Input: fruits = [1,2,1]
Output: 3
Explanation: All 3 trees can be picked.

Input: fruits = [0,1,2,2]
Output: 3
Explanation: The three trees [1,2,2] can be picked.
If you start picking from the first tree, you can only pick [0,1] these two trees.

Input: fruits = [1,2,3,2,2]
Output: 4
Explanation: The four trees [2,3,2,2] can be picked.
If you start picking from the first tree, you can only pick [1,2] these two trees.

Input: fruits = [3,3,3,1,2,1,1,2,3,3,4]
Output: 5
Explanation: The five trees [1,2,1,1,2] can be picked.

the code

class Solution(object):
    def totalFruit(self, fruits):
        """
        :type fruits: List[int]
        :rtype: int
        """
        ans=0
        i=0
        cnt = Counter() #Counter类统计出现次数,实现哈希表
        for j,x in enumerate(fruits): # 同时遍历得到数值
            cnt[x]+=1 #哈希表
            while len(cnt)>2:
                cnt[fruits[i]]-=1
                if cnt[fruits[i]]==0:
                    cnt.pop(fruits[i])
                i+=1
            ans=max(ans,j-i+1)
        
        return ans

class Solution {
    
    
public:
    int totalFruit(vector<int>& fruits) {
    
    
        int n = fruits.size();
        unordered_map<int, int> cnt;

        int left = 0, ans = 0;
        for (int right = 0; right < n; ++right) {
    
    
            ++cnt[fruits[right]];
            while (cnt.size() > 2) {
    
    
                auto it = cnt.find(fruits[left]);
                --it->second;
                if (it->second == 0) {
    
    
                    cnt.erase(it);
                }
                ++left;
            }
            ans = max(ans, right - left + 1);
        }
        return ans;
    }
};

Summarize

  • cnt = Counter() #Counter class counts the number of occurrences and implements a hash table
  • cnt[x]+=1 #hash table
  • In C++, unordered_map is a container that associates key and value, which can efficiently find the corresponding value based on a single key value

76. Minimum Covering Substring

topic

You are given a string s and a string t. Returns the smallest substring in s that covers all characters of t. Returns the empty string "" if no substring containing all the characters of t exists in s.

For a repeated character in t, the number of characters in the substring we are looking for must be no less than the number of characters in t.
If such a substring exists in s, we guarantee that it is the only answer.

Input: s = "ADOBECODEBANC", t = "ABC"
Output: "BANC"
Explanation: The minimal covering substring "BANC" contains 'A', 'B' and 'C' from string t.

Input: s = "a", t = "a"
Output: "a"
Explanation: The whole string s is the minimum covering substring.

Input: s = "a", t = "aa"
Output: ""
Explanation: The two characters 'a' in t should be included in the substring of s,
so there is no substring that meets the condition, and an empty string is returned .

the code

class Solution(object):
    def minWindow(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        need=Counter() #need=collections.defaultdict(int)
        for c in t:
            need[c]+=1
        needCnt=len(t)
        i=0
        res=(0,float('inf'))
        for j,c in enumerate(s):
            if need[c]>0:
                needCnt-=1
            need[c]-=1
            if needCnt==0:      #滑动窗口包含了所有T元素
                while True:      #增加i,排除多余元素
                    c=s[i] 
                    if need[c]==0:
                        break
                    need[c]+=1
                    i+=1
                if j-i<res[1]-res[0]:   #记录结果
                    res=(i,j)
                need[s[i]]+=1  #i增加一个位置,寻找新的满足条件滑动窗口
                needCnt+=1
                i+=1
        return '' if res[1]>len(s) else s[res[0]:res[1]+1]    #如果res始终没被更新过,代表无满足条件的结果

class Solution {
    
    
public:
    string minWindow(string s, string t) {
    
    
        vector<int> need(128,0);
        int count = 0;  
        for(char c : t)
        {
    
    
            need[c]++;
        }
        count = t.length();
        int l=0, r=0, start=0, size = INT_MAX;
        while(r<s.length())
        {
    
    
            char c = s[r];
            if(need[c]>0)
                count--;
            need[c]--;  //先把右边的字符加入窗口
            if(count==0)    //窗口中已经包含所需的全部字符
            {
    
    
                while(l<r && need[s[l]]<0) //缩减窗口
                {
    
    
                    need[s[l++]]++;
                }   //此时窗口符合要求
                if(r-l+1 < size)    //更新答案
                {
    
    
                    size = r-l+1;
                    start = l;
                }
                need[s[l]]++;   //左边界右移之前需要释放need[s[l]]
                l++;
                count++;
            }
            r++;
        }
        return size==INT_MAX ? "" : s.substr(start, size);
    }
};

Summarize

  • How to judge that the sliding window contains all the elements of T?
    We use a dictionary need to indicate the number of elements needed in the current sliding window. At the beginning, the sliding window is empty, and the elements in T are used to initialize the need. When the sliding window expands or shrinks, the need dictionary is maintained. For example, when the sliding window contains an element, we decrease the number of this element in need by 1, which means that the required element is reduced by 1; when the sliding window removes an element, we increase the number of this element in need by 1.
    need always records the number of elements we still need under the current sliding window. When we change i, j, we need to maintain need synchronously.

  • Optimize
    and maintain an additional variable needCnt to record the total number of required elements. When a required element c is encountered, the number of need[c] will be reduced by 1, and needCnt will also be reduced by 1, so that we can know whether the condition is met through needCnt. Instead of iterating through the dictionary.

  • Define array res=(0, float('inf'))

Guess you like

Origin blog.csdn.net/Magnolia_He/article/details/129884000