转载:https://blog.csdn.net/fly_yr/article/details/51134340
题目
最小子串覆盖
给定一个字符串source和一个目标字符串target,在字符串source中找到包括所有目标字符串字母的最小子串。
注意事项
如果在source中没有这样的子串,返回"",如果有多个这样的子串,返回长度最小的子串。
说明
在答案的子串中的字母在目标字符串中是否需要具有相同的顺序?
——不需要。
样例
给出source = "ADOBECODEBANC",target = "ABC" 满足要求的解 "BANC"
挑战
要求时间复杂度为O(n)
分析
采用哈希的思想,记录字母出现次数。
大小写字母的ASCII码不大于256,这样array['A']=3指A出现3次,array['B']=1指B出现了一次,以此类推,不能用常规意义上的定义array[0]=3表示A出现3次,这样就多了一层映射!故而数组的长度设置为256即可存放所有的字母。
首先预处理target,用256大小的整数数组tHash存储里面每个char出现的个数;
然后给定两个指标beg和end,一个移动start,也用一个256长的整数数组sHash记录从beg到end的这段字符串里面每个char出现的个数。如果sHash大于等于tHash,也就是说sHash里的每一位大于等于tHash里相应位置的值,找到当前start位置,为符合要求子串的起点,记录当前beg和end的长度,如果比已经记录的小,那么我们就选这个位最小窗口。记录beg和end。然后让start往前走一位。寻找下一个子串。
大小写字母的ASCII码不大于256,这样array['A']=3指A出现3次,array['B']=1指B出现了一次,以此类推,不能用常规意义上的定义array[0]=3表示A出现3次,这样就多了一层映射!故而数组的长度设置为256即可存放所有的字母。
首先预处理target,用256大小的整数数组tHash存储里面每个char出现的个数;
然后给定两个指标beg和end,一个移动start,也用一个256长的整数数组sHash记录从beg到end的这段字符串里面每个char出现的个数。如果sHash大于等于tHash,也就是说sHash里的每一位大于等于tHash里相应位置的值,找到当前start位置,为符合要求子串的起点,记录当前beg和end的长度,如果比已经记录的小,那么我们就选这个位最小窗口。记录beg和end。然后让start往前走一位。寻找下一个子串。
/*
32 最小子串覆盖
给定一个字符串source和一个目标字符串target,在字符串source中找到包括所有目标字符串字母的子串。
如果在source中没有这样的子串,返回"",如果有多个这样的子串,返回长度最小的子串。
说明
在答案的子串中的字母在目标字符串中是否需要具有相同的顺序?
——不需要。
样例
给出source = "ADOBECODEBANC",target = "ABC" 满足要求的解 "BANC"
*/
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
class Solution {
public:
/**
* @param source: A string
* @param target: A string
* @return: A string denote the minimum window
* Return "" if there is no such a string
*/
string minWindow(string &source, string &target) {
// write your code here
if (source.empty() || target.empty())
return "";
int sLen = source.length(), tLen = target.length();
vector<int> sHash(256, 0), tHash(256, 0);
/*建立源串的映射,存储每个字符的出现次数*/
for (int i = 0; i < tLen; ++i)
{
++tHash[target[i]];
}//for
/*记录符合要求的子串的位置,以及找到的字符个数*/
int beg = -1, end = sLen, found = 0, minLen = sLen;
for (int i = 0, start = i; i < sLen; ++i)
{
++sHash[source[i]];
/*更新当前找到的字符个数*/
if (sHash[source[i]] <= tHash[source[i]])
++found;
/*判断是否找到所有字符*/
if (found == tLen)
{
/*将源串开头未出现在目标串的字符跳过*/
while (start < i && sHash[source[start]] > tHash[source[start]])
{
--sHash[source[start]];
++start;
}//while
/*找到符合要求子串的首尾位置start 与 i*/
if (i - start < minLen)
{
minLen = i - start;
beg = start;
end = i;
}//if
/*跳过该子串的开头位置,寻找下一个子串*/
--sHash[source[start++]];
--found;
}//if
}//for
/*如果beg值为-1,说明不存在这样的子串*/
if (beg == -1)
return "";
else
return source.substr(beg, end - beg + 1);
}
};
int main()
{
Solution s;
string source = "ADOBECODEBANC", target = "BANC";
cout << s.minWindow(source, target) << endl;
system("pause");
return 0;
}