题目:
BM65 最长公共子序列(二):
找二者的相同部分,该部分对于二者可以不连续排列的(但是是有序的)。
BM66 最长公共子串
找二者的相同部分,该部分对于二者是连续排列的。
本题:BM90 最小覆盖子串
找s中包含t所有字符的部分,该部分对于s是连续排列的,对于t可以不连续排列(且可以没有顺序)。
模板的:
编程思想:采用滑动窗口法
- 窗口有左右两个指针。
- 找到一个符合条件(指包含t所有字符)的子串。
- 固定左指针,右指针往右走,
- 缩小窗口,找到最小字串。
- 固定右指针,左指针往左走。
- 记录最小的最小字串。
- 重复2和3,直到右指针走完。
编程细节:
- hash函数存储<key, slot>。
- hash.count(c) 表示计算hash表的key中有多少c。常用于查找hash表的key是否存在。hash.count 与 hash[]的区别,什么时候用.count,什么时候用hash[]?_hash_count-CSDN博客
- hash表的遍历:for(auto i = hash.begin(); i != hash.end(); i++){}
- 此时,key为i->first,slot为i->second。
- 考虑一些特殊用例:
- “abc”,"a",返回"a"
- 在while循环中,可能窗口的左指针在右指针的右边,但是因为不满足条件,很快右指针就往右走了。
- "a","aa",返回""
- 如果hash表在进行初始化时,key=t的每个元素,slot=0;更新hash表时,出现t的元素便加一;判断是否满足条件时,判断hash表的所有key的slot是等于0(不满足条件)还是大于0(满足条件)。这种做法的特点是,对t进行去重处理了。即返回"a"。
- 如果hash表在进行初始化时,key=t的每个元素,slot=t的每个元素出现次数的负数;更新hash表时,出现t的元素便加一;判断是否满足条件时,判断hash表的所有key的slot是小于0(不满足条件)还是等于0(满足条件)。这种做法的特点是,在hash表初始化时便记录了t重复元素的个数。即返回""。
- “abc”,"a",返回"a"
- 对字符串进行截取,比如,对str的[left,right]截取:
- return str.substr(left, right-left+1);
- return string(str.begin()+left, str.begin()+right+1);
题目要求时间复杂度是o(n),但是感觉模板的时间复杂度是o(n^2)。因为窗口在s上滑动时,要遍历所有t,判断窗口内是否包含t的全部元素。
#include <unordered_map>
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param S string字符串 * @param T string字符串 * @return string字符串*/bool check(unordered_map<char, int> &hash){for(auto i = hash.begin(); i != hash.end(); i++){if(i->second < 0)return false;}return true;}string minWindow(string S, string T) {// write code hereint n1 = S.size();int n2 = T.size();if(n1 == 0 || n2 == 0)return "";//用hash表来判断是否包含t的元素,对hash表进行初始化unordered_map<char, int> hash;for(int i = 0; i < n2; i++){hash[T[i]] --; //易错,初始化不用0,而用t元素个数的负数。}//用于记录int ans_r = -1;int ans_l = -1;int ans_cnt = n1;//指针,用于移动int p_r = 0;int p_l = 0;for(; p_r < n1; p_r++){//右指针每次往右,都要更新hash表。if(hash.count(S[p_r]))hash[S[p_r]] ++;//满足条件while(check(hash)){//记录if(ans_cnt >= p_r - p_l + 1){ans_cnt = p_r - p_l + 1;ans_r = p_r;ans_l = p_l;}//满足条件的前提下,缩小窗口,hash表也要更新。if(hash.count(S[p_l]))hash[S[p_l]] --;p_l ++;}}if(ans_l == -1) //粗心,忘记写return ""; return S.substr(ans_l, ans_r-ans_l+1);}
};