• 微软面试题: LeetCode 76. 最小覆盖子串 出现次数:2


    题目描述:

     题解:

       滑动窗口思想:用 i, j 表示滑动窗口的左边界和右边界,通过改变i,j来扩展和收缩滑动窗口,可以想象成一个窗口在字符串上游走,

    当这个窗口包含的元素满足条件,即包含字符串T的所有元素,记录下这个滑动窗口的长度j-i+1 和 窗口其实位置 i ,这些长度中的最小值

    对应的子串 就是要求的结果。设置一个变量 cnt 记录 滑动窗口中

       扩展滑动窗口 :向右 右边界移动  j 直到 窗口中的子串恰好覆盖 t 中所有字符时停止。(从不覆盖到覆盖)

       收缩滑动窗口: 向右移动左边界   i 直到 窗口中的子串恰好覆盖 t 中所有字符时停止。(再移动一步就不再覆盖,此时保存最小子串)

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 class Solution {
     4 public:
     5     string minWindow(string s, string t)
     6     {
     7         unordered_map<char,int> need;//记录 字符串t中的字符和出现的次数 
     8         unordered_map<char,int> window;// 记录滑动窗口内的字符和出现的次数
     9         for(int i = 0; i < t.size();++i)
    10         {
    11             need[t[i]]++;
    12         }
    13         const int t_cnt = need.size();
    14         int start = 0;//s中包含t中所有字符的最短子串起始下标
    15         int len = INT_MAX;//最短子串长度
    16         int cnt = 0;//t中的字符 在滑动窗口中已完备存在的个数
    17         int left = 0,right = 0;//滑动窗口左右边界
    18         char c = ' ';
    19         while (right < s.size())
    20         {
    21             //移动 right 扩大窗口,到窗口中的子串恰好覆盖 t 中所有字符时停止
    22             while (cnt < t_cnt && right < s.size())
    23             {
    24                 c = s[right];
    25                 if(need.find(c) != need.end())
    26                 {
    27                     if(++window[c] == need[c])
    28                     {
    29                         ++cnt;
    30                     }
    31                 }
    32                 ++right;
    33             }
    34             //right 移动到最右,滑动窗口内的子串仍然没有覆盖t中所有字符,直接返回之前得到的最小覆盖子串
    35             if(right == s.size() && cnt < t_cnt) 
    36             {
    37                 return len == INT_MAX?"":s.substr(start,len);
    38             }
    39             //移动left,收缩窗口,到窗口内的子串恰好覆盖 t 中所有字符时停止(再收缩一步就不再覆盖了)
    40             while(left < right && cnt == t_cnt)
    41             {
    42                 c = s[left];
    43                 if(need.find(c) != need.end())
    44                 {
    45                     if(window[c]-- == need[c])
    46                     {
    47                         --cnt;
    48                     }
    49                 }
    50                 ++left;
    51             }
    52             //此时的最小覆盖子串的范围应该是 [left-1,right-1]
    53             if(right - left + 1 < len )
    54             {
    55                 start = left - 1;
    56                 len = right - left + 1;
    57             }
    58         }
    59         return len == INT_MAX?"":s.substr(start,len);
    60     }
    61         
    62 };
  • 相关阅读:
    web应用后台开发的故事
    XML的定义、用途、以及它的发展前景和存在的问题等等
    本学期(大三下学期)学习目标
    企业级应用与互联网应用的区别?
    新能源汽车无线充电管理网站4
    新能源汽车无线充电管理网站3
    新能源汽车无线充电管理网站2
    企业级应用与互联网应用的区别
    javaee 新学期新目标
    团队项目PCP--自我评价
  • 原文地址:https://www.cnblogs.com/wangxf2019/p/14637206.html
Copyright © 2020-2023  润新知