题目
最小子串覆盖
给定一个字符串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;
- }
转自:https://blog.csdn.net/fly_yr/article/details/51134340