打卡 DAY 6 最小覆盖子串

力扣原题链接:滑动窗口类型题目

与上两题稍有不同的是这个需要记录每个字符出现的次数,在其他语言中使用哈希表,因为C语言没有哈希表,故定义一个数组代替。

思路:

由动图可知,需要一个数组来记录t中每个字母的频数(tFreq),另需要一个数组来记录滑动窗口中每个包含在t数组中的字母的频数 (winFreq),同时需要一个值来记录窗口中包含在t数组里的各个字母的总数与实际t数组中各个字母的总数的距离(distance)。

代码:

char* minWindow(char* s, char* t) {
    //z的ASCII码是122,为了避免越界,设大一点
    int winFreq[128] = { 0 };//记录窗口内各个目标字母的个数
    int tFreq[128] = { 0 };//记录t数组中各个目标字母的个数
    int slowIndex = 0;
    int fastIndex = 0;
    //假设区间为[slowIndex,fastIndex)
    int begin = 0;//定义输出s数组的第一个下标
    //记录t中各个字母的频数
    int i = 0;
    for (; t[i] != '\0'; i++) {
        tFreq[t[i]] ++;
    }
    int sNum = 0;//定义s数组的长度
    for (; s[sNum] != '\0'; sNum++);//计算s数组长度
    int distance = i;//记录t字符串中剩余没找到的字母的总数
    int minLen = sNum + 1;//作为判断是否输出空字符串的依据
    for (; s[fastIndex] != '\0'; fastIndex++) {//快指针遍历s数组
        char tem = s[fastIndex];
        if (tFreq[tem] != 0) {//当遇到t中字母时(因为目标字母的频数tFreq不会等于零)
            winFreq[tem] ++;//窗口中目标字母的个数加一
            if (winFreq[tem] <= tFreq[tem]) distance--;//当窗口中目标字母的频数还未大于t数组中目标字母频数时,剩余没找到的字母总数差值(distance)减一
        }
        if (distance == 0) {//当子数组中包含t所有字母
            if (minLen > (fastIndex - slowIndex + 1)) {//计算最小长度,并记录begin
                minLen = (fastIndex - slowIndex + 1);
                begin = slowIndex;
            }
            if (winFreq[s[slowIndex]] != 0) {//当慢指针所指为t中字母时
                if (winFreq[s[slowIndex]] == tFreq[s[slowIndex]]) distance++;
                winFreq[s[slowIndex]] --;
                slowIndex++;
            }
            for (; winFreq[s[slowIndex]] == 0; slowIndex++);//慢指针跳到下一个目标字母处
            if (slowIndex == fastIndex) continue;//当慢指针与快指针相同时,直接进入下次循环
            if (distance == 0 && minLen > (fastIndex - slowIndex + 1)) {//当窗口中包含所有目标字母时,计算最小长度,并记录begin(避免漏去目标字母相邻的情况e.g.s="BQBU" t="BU")
                minLen = (fastIndex - slowIndex + 1);
                begin = slowIndex;
            }
        }
    }
    if (minLen == sNum + 1) return "";//当minLen没变化时,说明不存在子数组,故输出空字符串
    char* res = malloc(sizeof(char) * (minLen + 1));
    res[minLen] = '\0';//将最后一(minLen-1)有效字母的后一位(minLen)设为终止符,不然老是有后边的奇怪的字符,不懂
    int n = 0;
    int p = begin;
    while (p < begin + minLen) {
        res[n ++] = s[p ++];
    }
    return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值