首页 > 编程语言 >【C++习题】16.滑动窗口_最小覆盖子串

【C++习题】16.滑动窗口_最小覆盖子串

时间:2024-11-27 22:02:07浏览次数:9  
标签:count right 16 ++ C++ hash1 hash2 习题 left

文章目录


题目链接:

76. 最小覆盖子串


题目描述:

2d825585388471865560b450c55e38d7


解法

暴力解法:

列出所有符合要求的字串,然后比较大小。

滑动窗口+哈希表

比如,如果已经符合要求了

95fa2613534042871b6dc9d74123fb42

那么left右移一位的话,right需要移动吗?

  1. left指向的地方恰好有符合t的字符,->right不动
  2. left指向的地方恰好没有符合t的字符,->right

解法:

  1. left=0,right=0

  2. 进窗口:hash2[in]++

  3. 判断:check(hash1,hash2)

    更新结果:起始位置,最短长度

    决定是否出窗口:hash2(out)--

我们可以优化一下:

使用count来标记有效字符的种类。

之前标记的是有效字符的次数,这边是种类,因为如果是次数的话,t里面是ABC1+1+1=3s里面是BBC,那么2+1=3,是无法解决这个问题的。

  1. 进窗口:进去之后,当hash2(in)==hash1(in);count++
  2. 出窗口:出之前,当hash2(out)==hash1(out);count--
  3. 判断条件:count==hash1.size()

C++ 算法代码:

class Solution 
{
    public:
    string minWindow(string s, string t) 
    {
        int hash1[128] = { 0 }; // 初始化一个大小为 128 的整型数组 hash1,并将所有元素初始化为 0
        int kinds = 0; // 统计有效字符有多少种
        for(auto ch : t){ // 遍历字符串t,统计每个字符的频次,并计算不同字符的种类数
            if(hash1[ch]++ == 0) 
            {
                kinds++;
            }
        }
        int hash2[128] = { 0 }; // 统计窗口内每个字符的频次
        int minlen = INT_MAX, begin = -1; // 记录最小窗口的长度,初始化为最大值,记录最小窗口的起始位置,初始化为-1
        for(int left = 0, right = 0, count = 0; right < s.size(); right++)
        {
            char in = s[right];// 当前进入窗口的字符
            if(++hash2[in] == hash1[in]) // 更新hash2中该字符的频次
            {
                count++; // 进窗口 + 维护 count
            }
            while(count == kinds) // 当count等于kinds时,说明当前窗口包含t中所有字符
            {
                if(right - left + 1 < minlen) // 更新最小窗口的长度和起始位置
                {
                    minlen = right - left + 1;
                    begin = left;
                }
                char out = s[left++]; // 尝试缩小窗口,移除最左边的字符
                if(hash2[out]-- == hash1[out]) 
                {
                    count--; // 出窗口 + 维护 count
                }
            }
        }
        if(begin == -1) // 如果begin没有被更新,说明不存在包含t的窗口,返回空字符串
        {
            return "";
        }
        else
        {
            return s.substr(begin, minlen);// 否则,返回从begin开始的最小窗口子串
        }
    }
};

图解

例如:s = "ADOBECODEBANC", t = "ABC"

2942e43d4a4a525ab279782a3897c60f

  1. hash1[A]=1,hash1[B]=1,hash1[C]=1,kind=3

    left = 0, right = 0, count = 0,进入循环

    in=A,++hash2[in]=2,hash1[in]=2,count++,count=1

    right++

d27563d756ba9ec63d28c3081577d037

  1. left = 0, right = 1, count = 1,进入循环

    in=D,++hash2[in]=2,hash1[in]=1,count=1

    right++

b63337b5d95f65a89d5cf1d8657eb638

  1. left = 0, right = 2, count = 1,进入循环

    in=O,++hash2[in]=2,hash1[in]=1,count=1

    right++

62f75e3d6dbfcf13d88a5fea42a78a61

  1. left = 0, right = 3, count = 1,进入循环

    in=B,++hash2[in]=2,hash1[in]=2,count++,count=2

    right++

c9c4a99fe7f9acc28f964ad4f936aaff

  1. left = 0, right = 4, count = 2,进入循环

    in=E,++hash2[in]=2,hash1[in]=1,count=2

    right++

19cf156b3919da67f0dd2c8ad83b28a0

  1. left = 0, right = 5, count = 2,进入循环

    in=C,++hash2[in]=2,hash1[in]=2,count++,count=3

    count == kinds,进入while循环

    right - left + 1 < minlen,进入if

    minlen = right - left + 1; minlen=5-0+1=6
    begin = left; begin=0

    char out = s[left++]; out=s[0]=A,left=1

    hash2[out]-- == hash1[out] == 3

    count--; count=2

    right++

fa3c2c04478ee08e99e65a6f64e16311

  1. left = 1, right = 6, count = 2,进入循环

    后面的过程一样,就不多赘述了。

标签:count,right,16,++,C++,hash1,hash2,习题,left
From: https://blog.csdn.net/hlyd520/article/details/144095577

相关文章

  • 【C++习题】15.滑动窗口_串联所有单词的子串
    文章目录题目链接:题目描述:解法C++算法代码:图解题目链接:30.串联所有单词的子串题目描述:解法滑动窗口+哈希表这题和第14题不同的是:哈希表不同:hash<string,int>left与right指针的移动不同:移动的步长是每个单词的长度滑动窗口执行的次数不同C++算法代......
  • C++命运石之门代码抉择:C++入门(中)
    文章目录3.C语言过渡到C++(中)3.1函数重载3.1.1函数重载的多种情况3.1.2函数重载的辨别3.1.3函数重载原理——名字修饰3.2引用3.2.1引用的概念3.2.2引用的特性3.2.3常引用3.2.3.1权限问题3.2.3.2类型转换3.2.4引用的使用3.2.4传值、传引用效率比较3.3内......
  • C++学习日记---第13天(类和对象---封装)
    笔记复习1.类和对象c++面向对象的三大特性为:封装,继承,多态c++认为万事万物都皆为对象,对象上有其属性和行为具有相同性质的对象,我们可以抽象为称为类2.封装作用:将属性和行为作为一个整体,表现生活中的事物,具有相同性质的对象,我们可以抽象为类。语法:class类名{访问权限(也可......
  • MCA架构师学员在北京,秋招收获京东物流offer,26.5k*16薪
    MCA架构师学员在北京,秋招收获京东物流offer,26.5k*16薪!马士兵教育2024最新版MCA互联网高级架构师课程,Java进阶从0到年薪百万机会在等你!_哔哩哔哩_bilibili......
  • 3166. 计算停车费与时长
    力扣题目跳转(3166.计算停车费与时长-力扣(LeetCode))表:ParkingTransactions+--------------+-----------+|ColumnName|Type|+--------------+-----------+|lot_id|int||car_id|int||entry_time|datetime||exit_ti......
  • 线性时间选择[C++,附代码]
    0引言问题:从无序数组中选择第k小的元素。1随机选择法1.1算法步骤:选择基准元素:随机选择一个元素作为基准。分区:对数组进行分区,使得基准元素左边的所有元素都小于它,右边的所有元素都大于它。分区过程完成后,我们得到了基准元素在数组中的位置pivotIndex。递归选择:如......
  • C++学习——函数返回数组
    首先不推荐函数返回数组,在C++中,函数不能直接返回一个本地数组,因为数组是分配在栈上的,当函数返回时,其栈帧会被销毁,因此返回的数组指针将会指向一个已释放的内存区域,这是未定义行为。不过,有几种方法可以用来从函数返回数组:文章目录1.返回指向数组的指针2.使用标准库容......
  • 【C++】C++11新特性详解:可变参数模板与emplace系列的应用
    C++语法相关知识点可以通过点击以下链接进行学习一起加油!命名空间缺省参数与函数重载C++相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C++内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现容器适配器Stack与QueuePriority......
  • c++QTableWidget横向填充满他的空间,且均匀分布
    1.概要//设置所有列均匀分布并填充满整个空间QHeaderView*header=tableWidget->horizontalHeader();for(inti=0;i<tableWidget->columnCount();++i){header->setSectionResizeMode(i,QHeaderView::Stretch);}2.内容在Qt中,如果你希望......
  • ZW3DC++调用C#的DLL
    C#:usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceTestWinform{publicclassClass1{publicvoidopenForm(){Form1form=newForm1();form.ShowDialog();}}}  C++:......