• 76. 最小覆盖子串


    76. 最小覆盖子串

    给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

    注意:

    • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
    • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

    示例 1:

    输入:s = "ADOBECODEBANC", t = "ABC"
    输出:"BANC"
    

    示例 2:

    输入:s = "a", t = "a"
    输出:"a"
    

    示例 3:

    输入: s = "a", t = "aa"
    输出: ""
    解释: t 中两个字符 'a' 均应包含在 s 的子串中,
    因此没有符合条件的子字符串,返回空字符串。

    提示:

    • 1 <= s.length, t.length <= 105
    • st 由英文字母组成
    进阶:你能设计一个在 o(n) 时间内解决此问题的算法吗?
     
     
    解析:
    vis数组统计一遍t中每个字符出现的次数,以及 令ans = t.length()
    首先先找一个符合的:
    nums用于数组统计s中的字符次数
    定义双指针,p = 0,q = 0;
    定义cnt = 0;表示当前能否满足t中每个字符一共出现ans个的要求(不算s中冗余的)
    如果s[q]在t中出现过则nums[s[q]]++;
      而且如果nums[s[q]] <= vis[s[q]], cnt++;
    如果cnt == ans,说明找到一个解
    while(s[p]没有出现过,或者nums[s[p]] > vis[s[p]]),那么p指向的字符没啥用,p++
    则p到q就是一个解
     
    求最优解:
    只要q < s.length(),就是q没到达末尾
    就将p向前一个字符,因为p当前的字符肯定是满足要求的,p向前一个就不满足了,这就促使q去找下一个字符,使之满足要求
    所以nums[s[p]]--, p++, q++, cnt--;
    class Solution {
    public:
        unordered_map<char, int> vis;
        unordered_map<char, int> nums;
        vector<string> ss;
        bool cal(int &p, int &q, int &ans, int &cnt, string s)
        {
            while(q < s.length())
            {
                if(vis[s[q]])
                {
                    nums[s[q]]++;
                    if(nums[s[q]] <= vis[s[q]]) cnt++;
                }
                if(cnt == ans) break;
                q++;
            }
            if(cnt < ans) return 0;
            while(p < q)
            {
                if(vis[s[p]])
                {
                    if(nums[s[p]] > vis[s[p]])
                    {
                        nums[s[p]]--;
                        p++;
                    }
                    else
                        break;
                }
                else p++;
            }
            string ret = "";
            for(int i = p; i <= q; i++)
                ret += s[i];
            ss.push_back(ret);
            return 1;
        }
    
        string minWindow(string s, string t) {
            for(int i = 0; i < t.length(); i++)
            {
                vis[t[i]]++;
            }
            int ans = t.length();
            int p = 0, q = 0;
            int cnt = 0;
            while(q < s.length())
            {
                if(cal(p, q, ans, cnt, s) == 0 && ss.size() == 0)
                    return "";
                nums[s[p]]--;
                p++;
                q++;
                cnt--;
                    
            }
            string temp = ss[0];
            int len = ss[0].length();
    
            for(int i = 0; i < ss.size(); i++)
            {
                if(ss[i].length() < len)
                {
                    len = ss[i].length();
                    temp = ss[i];
                }
            }
            return temp;
    
        }
    };
  • 相关阅读:
    MSSQL ADO.NET
    MSSQL 详解SQL Server连接(内连接、外连接、交叉连接)
    MSSQL DBOtherSQL
    java8时间转换成字符串
    泛型
    给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
    利用栈判断有效的括号
    回文数
    service层对 @NotBlank注解起作用
    集合的使用
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/16614744.html
Copyright © 2020-2023  润新知