LeetCode-Minimum Window Substring

本文解析了一道经典算法题目——寻找包含特定字符集的最小覆盖子串,并提供了一个高效的解决方案。通过使用双指针技术和哈希表,该算法能够在O(n)的时间复杂度内完成任务。
  • 题目描述:

    • Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

      For example,
      S = "ADOBECODEBANC"
      T = "ABC"

      Minimum window is "BANC".

    • Note:
      If there is no such window in S that covers all characters in T, return the emtpy string "".

      If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

    • 大意就是给定两个串,要求在第一个串中找到一个最小窗口,其中包含T中出现的所有字母(经过实验发现如果T中出现重复的字母,窗口也需要包含同样重复数量的字母。),如果找不到则返回空字符串。题目还要求了在O(n)的时间复杂度里完成整个过程。

  • 解题思路

    • 一开始觉得这道题目应该用动态规划来做,但是仔细考虑后发现这不同于最长递增子序列或者最大子序列和,这道题的信息并不只包含在一个字符串中而是需要两个字符串一起进行匹配。这样会造成一个结果就是动态规划所需的额外空间维度很高,并且我没有想到动态规划的O(n)算法。

    • 为了更快地记录和查询字符串中的信息,首先想到的就是使用哈希表。字符串有一个很好的特性就是每一个字符都有特定的ASCII,并且ASCII的可见字符是从32号开始的,所以开长度为96的数组就足够了。

      不过值得注意的是,考虑到T中可能会出现重字符的情况,所以我们需要构建两个haxibiao,一个是bool类型用来表示哪些字母出现在了T中,另一个用整型表示出现在T中的每个字符出现了多少次。

    • 设定好输出长度和输出起始位置,令其初始值分别为最大和最小。

    • 接下来使用两个指针,一个作为开头一个结尾。先让结尾指针向右,直到涵盖所有T出现的字母。这个时候查看是否可以更新输出长度。再让开头尽可能右移。不断重复这一步知道开头或结尾达到S长度。

    • 最后如果输出长度仍然为最大,则说明无解,否则输出解。

    • class Solution {
      public:
          string minWindow(string S, string T) {
              bool hash[96];memset(hash,0,sizeof(hash));
              int isIn[96];memset(isIn,0,sizeof(isIn));
              int m = T.length(), n = S.length();
              for(int i = 0; i < m ;++i){++isIn[T[i]-32];hash[T[i]-32] = 1;}
              int begin(0), end(-1);
              int minLen(1<<20), minIdx(0);
              while(begin<n&&end<n){
                  if(m){
                      ++end;
                      --isIn[S[end]-32];
                      if(hash[S[end]-32]&&isIn[S[end]-32] >= 0)m--;
                  }else{
                      if(minLen > end-begin+1){
                          minLen = end-begin+1;
                          minIdx = begin;
                      }
                      ++isIn[S[begin]-32];
                      if(hash[S[begin]-32]&&isIn[S[begin]-32]>0)++m;
                      ++begin;
                  }
              }
              if(minLen == (1<<20))return "";
              return S.substr(minIdx,minLen);
          }
      };

      224936_mojb_1450942.jpg



转载于:https://my.oschina.net/xueyang/blog/385951

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值