[H哈希] lc76. 最小覆盖子串(双指针+滑动窗口+哈希+线性优化)

1. 题目来源

链接:76. 最小覆盖子串

2. 题目解析

前导题:

在这一开始写了个 cnt == ht.size(),又进一步加深了 unordered_map 的理解。不论对其赋不赋值,均会进行插入操作!!一定牢记这点。

思路还是很常规的,套用了第三题的双指针思想,及第 30 题的一小部分快速判断区间字符是否覆盖的思想。蛮重要的两个思想。

在这里插入图片描述

注意:

  • 本题的采用的 “有效字符” 概念,是一个非常重要的线性做法的概念。
  • 非线性做法,可能会去使用两个哈希表比较元素是否完全涵盖的做法,这样会产生很多无用计算。

代码:

线性做法:

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char, int> hs, ht;
        for (auto e : t) ht[e] ++ ;
        
        string res;
        int cnt = 0;
        for (int i = 0, j = 0; i < s.size(); i ++ ) {
            hs[s[i]] ++ ;// 先加入哈希表中,若加入后该字符小于等于有效字符的个数则说明该操作有效
            if (hs[s[i]] <= ht[s[i]]) cnt ++ ;	// 等号不能丢...一开始想错了

            while (hs[s[j]] > ht[s[j]]) hs[s[j ++ ]] -- ;
            if (cnt == t.size()) {
                if (i - j + 1 < res.size() || res.empty())
                    res = s.substr(j, i - j + 1);
            }
        }
        return res;
    }
};

2024年09月23日01:05:11
上面这个 cnt 的引入,感觉不是很好想出来。

  • 如果 s 的字符纳入进来,却又没超过 t 中的字符限制的话,说明这个字符的纳入是有效的,反之是无效的。
  • 最后通过,cnt == t.size() 来判断是否可以更新答案。

可以用一个比较慢的做法,去判断哈希表中的所有字符是否是有效的了,再去更新答案。

  • 这个做法比较慢,因为每次我们只是拓展 j 的下标所在字符,然而还是需要将哈希表中的所有字符拿出来比较一遍,看看是不是合法字符。这里产生了很多无用计算。

这里的判断需要按照字符类别来,如果是小写字母的话,就是 26,如果是大写的话,就是 52 了。

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char, int> ms, mt;
        for (char c : t) mt[c] ++ ;

        string res = "";
        for (int i = 0, j = 0; j < s.size(); j ++ ) {
            ms[s[j]] ++ ;
            bool ck = true;
            for (auto [k, v] : mt) {
                if (ms[k] < v) {
                    ck = false;
                    break;
                }
            }
            
            while (ms[s[i]] > mt[s[i]]) ms[s[i ++ ]] -- ;
            if (ck && (res == "" || j - i + 1 < res.size())) 
                res = s.substr(i, j - i + 1);
        }

        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值