904.水果成篮、76. 最小覆盖子串(滑动窗口解法)

904. 水果成篮

题目描述:你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

解答:

采用滑动窗口法,窗口内存放可采摘的果树;起始位置在窗口内的两种果树扩展完毕时进行移动,移动至第二类的开始处;终止位置用于在存在可行解时寻找最优解。

代码思路:首先从当前位置起,寻找第二种果树,找到后终止位置向后扩展寻找最优解,若最优解大于已有的result则进行更新。寻找结束后,起始位置移动至第二种果树的开始处,继续往下寻找,直到寻找结束为止。

代码实现:

class Solution {
public:
    int totalFruit(vector& fruits) {
        int temp, sub1=0, sub2=0, j=0, result=INT_MIN;
        //temp临时储存的可行解值
        //两个sub是两种水果
        //result 最后的结果
        int location = 0;
        for ( int i=0; i result ? temp : result;//寻找最大的解
                j ++; //右边界扩展
                if ( j==fruits.size() ) //右边界到达临界值
                {
                    return result == INT_MIN ? 0 : result;
                    //没有给result赋值就是没有可行解
                }
            } 
        }
        return result; //无关 不会执行到
    }
};

76. 最小覆盖子串

题目描述:

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

注意:对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。

解答:采用滑动窗口法。我们在 s 上滑动窗口,通过移动 r 指针不断扩张窗口。当窗口包含 t 全部所需的字符后,如果能收缩,我们就收缩窗口直到得到最小窗口。(来自leetcode官方题解)

此处如果用每个都进行寻找的办法复杂度就太高了,采用了哈希表进行比较。

可以用一个哈希表表示 t中所有的字符以及它们的个数,用一个哈希表动态维护窗口中所有的字符以及它们的个数,如果这个动态表中包含 t 的哈希表中的所有字符,并且对应的个数都不小于 t 的哈希表中各个字符的个数,那么当前的窗口是「可行」的。

注意:这里 t 中可能出现重复的字符,所以我们要记录字符的个数

代码实现:

class Solution {
public:
    string minWindow(string s, string t) {
        if(s.size() < t.size())
            return "";
        //创建hash表存储s中还应出现的字符,hash表中表项等于t中字符 种类
        maphash_map;
        //对于t中的字符串,存储至hash表中。已经有了的计数加1,没有的置为1
        for(auto c:t)
            hash_map[c] = hash_map.find(c) != hash_map.end() ? hash_map[c] + 1 : 1;
        int left=0, right=0;//左右边界
        int count=0;//记录已有字符串长度,当其等于t的长度时表示寻找到了一个子串
        int minleft=0, minright=0;
        int minlength=INT32_MAX;
        for (; right < s.size(); right++){
            if (hash_map.find(s[right]) != hash_map.end()){//右边界移动寻找满足count == t.size()
                if (hash_map[s[right]] >0 )
                    count++;
                hash_map[s[right]]--;
            }
            while(count == t.size()){//此时左边界移动,寻找最小的子串
                if (right - left + 1 < minlength){
                    minlength = right - left + 1;
                    minleft = left;
                    minright = right;
                }
                if (hash_map.find(s[left]) != hash_map.end()){//移动时注意处理串中情况
                    if (hash_map[s[left]] >= 0 ){
                        count--;
                    }
                    hash_map[s[left]]++;
                }
                left++;
            }
        }
        if (minlength != INT32_MAX)
            return string(s.begin()+minleft,s.begin()+minright+1);
        else 
            return "";
    }
};

你可能感兴趣的:(leetcode刷题,算法,leetcode,c++)