zoukankan      html  css  js  c++  java
  • 微软面试题: 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 };
  • 相关阅读:
    tornado硬件管理系统-数据存储与表格实时监控(8)
    db2 内存研究
    Oracle dml开始到commit期间的流程
    用户界面与业务逻辑的分离
    计算器核心算法——终结版
    计算器核心算法——中缀表达式转为后缀表达式
    计算器核心解析算法(上)
    Qt中的字符串类
    初探Qt中的消息处理
    计算器界面代码重构
  • 原文地址:https://www.cnblogs.com/wangxf2019/p/14637206.html
Copyright © 2011-2022 走看看