Minimum Window Substring 最小覆盖子串算法

题目

 最小子串覆盖

给定一个字符串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往前走一位。寻找下一个子串。

代码

[csharp]  view plain  copy
  1. /* 
  2. 32 最小子串覆盖 
  3.  
  4. 给定一个字符串source和一个目标字符串target,在字符串source中找到包括所有目标字符串字母的子串。 
  5. 如果在source中没有这样的子串,返回"",如果有多个这样的子串,返回长度最小的子串。 
  6. 说明 
  7. 在答案的子串中的字母在目标字符串中是否需要具有相同的顺序? 
  8. ——不需要。 
  9. 样例 
  10. 给出source = "ADOBECODEBANC",target = "ABC" 满足要求的解  "BANC" 
  11. */  
  12.  
  13. #include <iostream>  
  14. #include <cstdlib>  
  15. #include <vector>  
  16. #include <string>  
  17. #include <algorithm>  
  18.   
  19. using namespace std;  
  20.   
  21. class Solution {  
  22. public:  
  23.     /** 
  24.     * @param source: A string 
  25.     * @param target: A string 
  26.     * @return: A string denote the minimum window 
  27.     *          Return "" if there is no such a string 
  28.     */  
  29.     string minWindow(string &source, string &target) {  
  30.         // write your code here  
  31.         if (source.empty() || target.empty())  
  32.             return "";  
  33.   
  34.         int sLen = source.length(), tLen = target.length();  
  35.         vector<int> sHash(256, 0), tHash(256, 0);  
  36.         /*建立源串的映射,存储每个字符的出现次数*/  
  37.         for (int i = 0; i < tLen; ++i)  
  38.         {  
  39.             ++tHash[target[i]];  
  40.         }//for  
  41.   
  42.         /*记录符合要求的子串的位置,以及找到的字符个数*/  
  43.         int beg = -1, end = sLen, found = 0, minLen = sLen;  
  44.         for (int i = 0, start = i; i < sLen; ++i)  
  45.         {  
  46.             ++sHash[source[i]];  
  47.             /*更新当前找到的字符个数*/  
  48.             if (sHash[source[i]] <= tHash[source[i]])  
  49.                 ++found;  
  50.             /*判断是否找到所有字符*/  
  51.             if (found == tLen)  
  52.             {  
  53.                 /*将源串开头未出现在目标串的字符跳过*/  
  54.                 while (start < i && sHash[source[start]] > tHash[source[start]])  
  55.                 {  
  56.                     --sHash[source[start]];  
  57.                     ++start;  
  58.                 }//while  
  59.                 /*找到符合要求子串的首尾位置start 与 i*/  
  60.                 if (i - start < minLen)  
  61.                 {  
  62.                     minLen = i - start;  
  63.                     beg = start;  
  64.                     end = i;  
  65.                 }//if  
  66.                 /*跳过该子串的开头位置,寻找下一个子串*/  
  67.                 --sHash[source[start++]];  
  68.                 --found;  
  69.             }//if  
  70.         }//for  
  71.   
  72.         /*如果beg值为-1,说明不存在这样的子串*/  
  73.         if (beg == -1)  
  74.             return "";  
  75.         else  
  76.             return source.substr(beg, end - beg + 1);  
  77.     }  
  78. };  
  79.   
  80. int main()  
  81. {  
  82.     Solution s;  
  83.     string source = "ADOBECODEBANC", target = "BANC";  
  84.   
  85.     cout << s.minWindow(source, target) << endl;  
  86.   
  87.     system("pause");  
  88.     return 0;  
  89. }  
GitHub源码

转自:https://blog.csdn.net/fly_yr/article/details/51134340

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值