算法2:滑动窗口(下)

news2024/11/16 19:46:28

文章目录

  • 水果成篮
  • 找到字符串中所有字母异位词
  • 串联所有单词的子串*
  • 最小覆盖子串*

水果成篮

在这里插入图片描述
两元素排空操作
窗口中存在元素交错情况,所以出窗口一定要出干净!!!

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        unordered_map<int, int> hash; // 统计水果情况
        int res = 0;
        for (int left = 0, right = 0; right < fruits.size(); right++) {
            hash[fruits[right]]++;  // 进窗口
            while (hash.size() > 2) // 判断
            {
                // 出窗口
                hash[fruits[left]]--;
                if (hash[fruits[left]] == 0)
                    hash.erase(fruits[left]);
                left++;
            }
            res = max(right - left + 1, res);
        }
        return res;
    }
};

优化:

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int hash[100001] = {0}; // 统计水果情况
        int res = 0;
        for (int left = 0, right = 0, kinds = 0; right < fruits.size();
             right++) {
            if (hash[fruits[right]] == 0)
                kinds++;           // 维护水果种类
            hash[fruits[right]]++; // 进窗口
            while (kinds > 2)      // 判断
            {
                // 出窗口
                hash[fruits[left]]--;
                if (hash[fruits[left]] == 0)
                    kinds--;
                left++;
            }
            res = max(right - left + 1, res);
        }
        return res;
    }
};

技巧:数据有限的情况下,用数组比用容器快很多

找到字符串中所有字母异位词

在这里插入图片描述

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        if (s.size() < p.size())
            return {};

        vector<int> res;
        long long sum = 0;
        for (auto e : p)
            sum += (e - '0') * (e - '0') * (e - '0');

        int left = 0, right = 0;
        long long target = 0;
        while (right < s.size()) {
            target += (s[right] - '0') * (s[right] - '0') * (s[right] - '0');
            while (target >= sum && left <= right) {
                if (target == sum && right - left == p.size() - 1)
                    res.push_back(left);
                target -= (s[left] - '0') * (s[left] - '0') * (s[left] - '0');
                left++;
            }
            right++;
        }
        return res;
    }
};
class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        if (s.size() < p.size())
            return {};

        int hash1[26] = {0};
        for (auto e : p)
            hash1[e - 'a']++;

        vector<int> res;
        int hash2[26] = {0};
        int m = p.size();
        for (int left = 0, right = 0, count = 0; right < s.size(); right++) {
            char in = s[right];
            if (++hash2[in - 'a'] <= hash1[in - 'a']) // 进窗口及维护count
                count++;
            if (right - left + 1 > m) // 判断
            {
                char out = s[left++];
                if (hash2[out - 'a']-- <= hash1[out - 'a'])
                    count--; // 出窗口及维护count
            }
            // 结果更新
            if (count == m)
                res.push_back(left);
        }

        return res;
    }
};

串联所有单词的子串*

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        int slen = s.size(), plen = words.size(), _size = words[0].size();
        plen *= _size;
        if (plen == 0 || slen < plen)
            return {};

        // 滑动窗口+哈希表
        vector<int> res;
        unordered_map<string, int> aCount;
        for (auto& e : words)
            aCount[e]++;

        unordered_map<string, int> bCount;
        int n = words[0].size();
        while (n--) /// 执行n次滑动窗口
        {

            for (int left = n, right = n, count = 0; right + _size <= s.size();
                 right += words[0].size()) {
                string in = s.substr(right, words[0].size());
                bCount[in]++;
                // if(aCount[in] && bCount[in] <= aCount[in])   count++;
                if (aCount.count(in) && bCount[in] <= aCount[in])
                    count++;

                // 这里窗口的长度是right + len -left,
                // 也就是说窗口的长度已经大于words的总体长度
                if (right - left == words[0].size() * words.size()) {
                    string out = s.substr(left, words[0].size());

                    // 这里用[]会影响速度,用哈希的计数函数快一些
                    // count函数的返回值是0或1
                    // ,类似于bool值,表示其是否存在,而[]返回的是次数,就涉及到了查找,故花费时间较长
                    if (aCount.count(out) && bCount[out] <= aCount[out])
                        count--;
                    // if(aCount[out] && bCount[out] <= aCount[out]) count--;

                    bCount[out]--;
                    left += words[0].size();
                }

                if (count == words.size())
                    res.push_back(left);
            }
            bCount.clear();
        }
        return res;
    }
};

```cpp
class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> result;
        if (s.empty() || words.empty())
            return result;

        int word_length = words[0].length();
        int num_words = words.size();
        int total_length = word_length * num_words;

        unordered_map<string, int> word_count;
        for (const string& word : words) {
            word_count[word]++;
        }

        for (int i = 0; i < word_length; ++i) {
            int left = i, right = i;
            unordered_map<string, int> window_count;

            while (right + word_length <= s.length()) {
                string word = s.substr(right, word_length);
                right += word_length;

                if (word_count.find(word) != word_count.end()) {
                    window_count[word]++;

                    while (window_count[word] > word_count[word]) {
                        string left_word = s.substr(left, word_length);
                        window_count[left_word]--;
                        left += word_length;
                    }

                    if (right - left == total_length) {
                        result.push_back(left);
                    }
                } else {
                    window_count.clear();
                    left = right;
                }
            }
        }
        return result;
    }
};

两段代码都是:哈希+滑动窗口,时间空间复杂度也一样,但是测试时间却减少了许多,可以对比一下第二段代码优于第一段代码的点在哪里?

最小覆盖子串*

在这里插入图片描述

在这里插入图片描述

class Solution {
public:
    string minWindow(string s, string t) {
        string res;
        int hash[128] = {0};
        int tt = 0; // 字符种类
        for (char& e : t)
            if (0 == hash[e]++)
                tt++;

        int hash1[128] = {0};
        int begin = -1, m = INT_MAX;
        for (int left = 0, right = 0, count = 0; right < s.size(); right++) {
            // 进窗口
            char in = s[right];
            if (++hash1[in] == hash[in])
                count++;
            //  检查
            while (count == tt) {
                //  更新
                if (right - left + 1 < m) {
                    begin = left;
                    m = right - left + 1;
                }
                //  出窗口
                char out = s[left++];
                if (hash1[out]-- == hash[out])
                    count--;
            }
        }
        if (begin != -1)
            res = s.substr(begin, m);
        return res;
    }
};
//  "ADOBEC"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1800198.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VS2019创建c++动态链接库dll与调用方法

VS2019创建c动态链接库dll与调用方法 1.点击文件-》新建-》项目&#xff0c;输入dll,选择具有导出项的(DLL)动态链接库 2.输入一个文件名&#xff1a;dll2 头文件.h 3.添加加减法函数&#xff1a; // 下列 ifdef 块是创建使从 DLL 导出更简单的 // 宏的标准方法。此 DLL 中的…

【雷达原理】一维CFAR检测算法——对比分析与代码实现

目录 引言一、仿真实例1.1 均匀背景杂波1.2 杂波边缘1.3 多干扰目标杂波 二、MATLAB代码参考文献 引言 推荐博文【目标检测】雷达目标CFAR检测算法 上述文章介绍了四种典型CFAR检测算法的特点及性能对比。本文将利用MATLAB进行仿真&#xff0c;通过实例验证和对比这几种算法的…

MFC 使用sapi文字转换为语音

文章目录 添加头文件声明变量 添加头文件 声明变量 pSpVoice NULL; //默认构造函数中初始化为空 bool CChKBarSCCodeApp::InitSpVoice() {HRESULT hr ::CoInitialize(NULL); // COM初始化if (!SUCCEEDED(hr)){AfxMessageBox(_T("声音环境初始化失败&#xff01;…

拼接屏处理器

拼接屏系统由三大部分组成&#xff0c;即拼接墙、液晶拼接处理器和信号源。其中液晶拼接处理器是关键技术的核心&#xff0c;支持不同像素的图像在大屏显示墙上显示以及在大屏显示墙上任意开窗口、BSV画面叠加、窗口放大缩小、跨屏漫游显示等。液晶拼接处理器一般分为两种&…

【grafana】创建多变量table

这个普罗米修斯的指标啊&#xff0c;大多数都是键值对&#xff0c;而且笔者如果没记错&#xff0c;他这个值还必须是浮点。少数可以设成离散值&#xff08;Enum&#xff09;&#xff0c;但本质还是一个带翻译功能的键值对 这样的好处是&#xff0c;做起来非常简单&#xff0c;…

利用梯度提升树分类法实现乳腺癌数据集分类

目录 1. 作者介绍2. 梯度提升树算法2.1 Boosting 算法2.2 Boosting Tree &#xff08;提升树&#xff09;2.3 梯度提升树&#xff08;Gradient Boosting Tree&#xff09; 3. 利用梯度提升树分类法实现乳腺癌数据集分类实验3.1 乳腺癌数据集介绍3.2 实验过程3.3 实验结果3.4 完…

突破语言与文化壁垒:海外短剧推广平台多语言支持技术的重要性与实施

在全球化的今天&#xff0c;语言和文化差异成为了海外短剧推广的一大挑战。为了吸引全球观众&#xff0c;海外短剧推广平台必须提供多语言支持&#xff0c;以突破语言与文化壁垒。本文将强调多语言支持的重要性&#xff0c;并探讨其实现技术。 一、多语言支持的重要性 随着全…

[网鼎杯 2020 青龙组]jocker

运行程序,发现是要我们自己输入 那么肯定是拿到enc慢慢还原 32位,无壳 进来就红一下报错 这里可以看见长度为24 动调一下看看 这里进行了大量的异或 这里是对地址开始的硬编码进行异或,从而达到smc的效果 所以你也可以发现在进行这一步操作之前 encry函数全是报错 你点开…

经纬恒润助力红旗转向技术新突破

近日&#xff0c;红旗研发新视界发布《国内首发&#xff01;红旗大输出力冗余平行轴式电动助力转向器让用户出行经济又安全&#xff01;》 &#xff0c;创新突破“输出力20kN以上的冗余平行轴式电动助力转向器&#xff08;R-EPS&#xff09;”。该产品支持整车实现L2/L3级自动驾…

苹果Safari怎么清理缓存?原来快速清除浏览器的历史记录那么容易

在数字化时代&#xff0c;互联网已经成为我们日常生活中不可或缺的一部分。我们使用各种设备&#xff0c;如智能手机、平板电脑和笔记本电脑来浏览网页、获取信息、娱乐和社交。而在这些设备中&#xff0c;iPhone无疑是最受欢迎的选择之一。iPhone搭载的Safari浏览器以其简洁的…

AIConnect赋能加持丨AI+DEPIN 共同推动AI发展的技术与运用峰会圆满落幕

6月6日&#xff0c;由AIConnect主办&#xff0c;JuCoin协办的「AIDePIN 共同推动AI发展的技术与应用」峰会在胡志明市圆满落幕&#xff01;此次活动不仅是AIConnect生态在市场推广和技术应用方面的重要一步&#xff0c;也标志着JuCoin在推动AI与DePIN技术融合中的又一里程碑。 …

车载开发之预置无源码apk到Android系统(带so文件)

1.在 packages/apps 下面以需要预置的 APK 名字创建文件夹&#xff0c;以预置一个名为 CarNavi 的APK为例。 新建一个CarNavi 的文件夹&#xff0c;在系统里面&#xff0c;如下图所示&#xff08;我的系统路径&#xff1a;/home/ts/project/NewAosp/Android/packages/apps/Car…

外卖APP与外卖小程序开发:从源码到上线的全流程

本文&#xff0c;小编将详细介绍外卖系统与小程序开发的全过程&#xff0c;从源码的编写到系统的上线&#xff0c;为开发者提供全面的指导。 一、需求规划 用户需要一个简单易用的点餐界面&#xff0c;商家需要管理菜单、订单和配送&#xff0c;后台管理则需要监控系统运行状况…

【力扣第 400 场周赛】Leetcode 删除星号以后字典序最小的字符串

文章目录 1. 删除星号以后字典序最小的字符串 1. 删除星号以后字典序最小的字符串 题目链接 &#x1f34e; 解题思路&#xff1a;遇到 *就删除一个字符&#xff0c;为了满足题意&#xff0c;要删除字典序最小的字符&#xff0c;那么假如有多个字典序最小的字符我们该删除哪个…

嵌入式Linux系统中RTC应用的操作详解

第一:RTC的作用以及时间简介 “RTC”的英文全称是Reul-Time Clock,翻译过来是实时时钟芯片.实时时钟芯片是日常生活中应用最为广泛的电子器件之一,它为人们或者电子系统提供精确的实时时间,实时时钟芯片通过引脚对外提供时间读写接口,通常内部带有电池,保证在外部系统关…

【QT5】<总览四> QT常见绘图、图表及动画

文章目录 前言 一、QFile类读写文件 二、QPainter绘简单图形 三、QChart图表 四、QPropertyAnimation属性动画 五、Q_PROPERTY宏简介 六、自定义属性动画 前言 承接【QT5】&#xff1c;总览三&#xff1e; QT常用控件。若存在版权问题&#xff0c;请联系作者删除&#…

【学习笔记】Windows GDI绘图(十三)动画播放ImageAnimator(可调速)

文章目录 前言定义方法CanAnimate 是否可动画显示Animate 动画显示多帧图像UpdateFramesStopAnimate终止动画Image.GetFrameCount 获取动画总帧数Image.GetPropertyItem(0x5100) 获取帧延迟 自定义GIF播放(可调速) 前言 在前一篇文章中用到ImageAnimator获取了GIF动画的一些属…

Ubuntu 22.04.4 LTS安装cmake-3.29.5

一、下载源码 wget https://github.com/Kitware/CMake/releases/download/v3.29.5/cmake-3.29.5.tar.gz tar -xzvf cmake-3.29.5.tar.gz 二、编译 运行./bootstrap。 如果出现下列问题&#xff1a; -- Could NOT find OpenSSL, try to set the path to OpenSSL root folder …

一个案例,剖析攻防演练中威胁溯源的正确姿势

一年一度的攻防演练即将拉开帷幕。“威胁溯源”一直是演练活动中一个十分重要的工作项&#xff0c;它不仅有助于理解和分析攻击的来源、方法和动机&#xff0c;还能够显著提升整体安全防护水位&#xff0c;提升组件与人员的联动协作能力。在真实的攻击场景中&#xff0c;溯源工…

QT 如何在 QListWidget 的选项中插入自定义组件

有时我们需要 QListWidget 完成更复杂的操作&#xff0c;而不仅限于添加文本或者图标&#xff0c;那么就会使用到 setItemWidget 函数&#xff0c;但是这也会伴生一个问题&#xff0c;插入自定义组件后&#xff0c;QListWidget 对选项点击事件的获取会收到阻塞&#xff0c;因…