算法2:滑动窗口(下)

文章目录

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

水果成篮

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

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"

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI图书推荐:《如何利用ChatGPT在线赚钱》

这本书《如何利用ChatGPT在线赚钱》&#xff08;$100m ChatGPT_ How To Make Money Online With ChatGPT -- Sharp, Biily -- 2023 &#xff09;主要阐述如何利用ChatGPT这一强大的语言模型工具在互联网上创造收入。 以下是各章节内容的概要&#xff1a; **引言** - 介绍了Chat…

机器学习——多层感知机

感知机 缺点&#xff1a;只能处理线性问题&#xff0c;感知机无法解决异或问题 在这里偏置就像线性模型的常数项&#xff0c;加入偏置模型的表达能力增强&#xff0c;而激活函数就像示性函数&#xff0c;可以模拟神经元的兴奋和抑制&#xff0c;当大于等于0就输出1。 多层感…

从军事角度理解“战略与战术”

战略与战术&#xff0c;均源于军事术语。 战略&#xff08;Strategy&#xff09;&#xff0c;源自希腊语词汇“strategos&#xff08;将军&#xff09;”和“strategia&#xff08;军事指挥部&#xff0c;即将军的办公室和技能&#xff09;”。指的是指挥全局性作战规划的谋略…

网络基础_02

1.ARP协议 地址解析协议&#xff08;Address Resolution Protocol&#xff09; 已知对方的三层ip地址&#xff0c;需要二层mac地址 当一台设备&#xff08;请求方&#xff09;需要知道某个 IP 地址对应的 MAC 地址时&#xff0c;会使用 ARP封装一个数据帧。这台设备的网络层以…

[职场] 为什么不能加薪? #学习方法#知识分享#微信

为什么不能加薪&#xff1f; 不能加薪的根本原因&#xff0c;终于被我找到了&#xff01; 朋友们&#xff01;职场这个地方是个很神奇的世界&#xff0c;有些规则并不是你想象的那样。我们都希望能在这个世界里施展自己的才华&#xff0c;获得升职加薪的荣耀。然而&#xff0c…

Blender 学习笔记(二)游标与原点

1. 游标 游标是界面中的红色圆圈&#xff1a; 1.1 移动游标 我们可以通过点击工具栏中的游标按钮&#xff0c;来移动游标&#xff0c;或者通过快捷键 shift右键 移动。若想要重置复游标位置&#xff0c;可以用 shiftc 恢复&#xff0c;或则通过 shifts 点击 游标->世界原…

Python中的Paramiko与FTP文件夹及文件检测技巧

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; Python代码的魅力与实用价值 在当今数字化时代&#xff0c;编程已成为一种不可或缺的技能。Python作为一种简洁、易读且功能强大的编程语言&#xff0c;受到了全球开发者的喜爱。它不仅适用于初学者入门&#xff0c…

Java 数据库连接(JDBC)的使用,包括连接数据库、执行SQL语句等

一、简介 Java Database Connectivity&#xff08;JDBC&#xff09;是Java应用程序与关系数据库进行交互的一种API。它提供了一组用于访问和操作数据库的标准接口&#xff0c;使开发人员能够使用Java代码执行数据库操作&#xff0c;如查询、插入、更新和删除等。 二、JDBC架构…

C++ AVL树 详细讲解

目录 一、AVL树的概念 二、AVL树的实现 1.AVL树节点的定义 2.AVL树的插入 3.AVL树的旋转 4.AVL树的验证 三、AVL树的性能 四、完结撒❀ 一、AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但 如果数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;查 …

SQL进阶day11——窗口函数

目录 1专用窗口函数 1.1 每类试卷得分前3名 1.2第二快/慢用时之差大于试卷时长一半的试卷 1.3连续两次作答试卷的最大时间窗 1.4近三个月未完成试卷数为0的用户完成情况 1.5未完成率较高的50%用户近三个月答卷情况 2聚合窗口函数 2.1 对试卷得分做min-max归一化 2.2每份…

m3u8视频怎么打开?教你三招!

m3u8 是一种文本文件格式&#xff0c;用于创建媒体播放列表&#xff0c;现在大部分的视频流媒体都是m3u8格式。当我们从网上下载下来m3u8文件的时候会发现&#xff0c;它本身不是一段视频&#xff0c;而是一个索引纯文本文件。想要正常打开播放m3u8视频其实也很简单&#xff0c…

解码 LangChain | LangChain + GPTCache =兼具低成本与高性能的 LLM

LangChain 联合创始人 Harrison Chase 提到&#xff0c;多跳问题会给语义检索带来挑战&#xff0c;并提出可以试用 AI 代理工具解决。不过&#xff0c;频繁调用 LLM 会导致出现使用成本高昂的问题。 对此&#xff0c;Zilliz 软件工程师 Filip Haltmayer 指出&#xff0c;将 GP…

塑造财务规划团队的未来角色

随着企业不断改革&#xff0c;其财务规划团队的格局也在不断变化&#xff0c;领先行业的专业人士已经开始利用更创新的财务知识和思维来驾驭现代化财务规划角色的复杂性。财务团队需要不同的职能角色和技能组合来支持其发展&#xff0c;多学科团队和跨职能协作带来的挑战和机遇…

C语言详解(动态内存管理)1

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

MacBook Pro上高cpu上不断重启运行的efilogin-helper

高 cpu 运行这个不知道干什么的进程&#xff0c;让风扇疯狂输出&#xff0c;让人甚是烦躁&#xff0c;苹果社区里的回答比较抽象&#xff0c;要么换设备&#xff0c;要么重装。 尝试过找到这个文件&#xff0c;删了部分内容&#xff0c;无果。。。 stack overflow 有个回答&a…

stm32驱动直流电机实现启动/加速/减速/倒车/停车等功能

不积跬步&#xff0c;无以至千里&#xff1b;不积小流&#xff0c;无以成江海。 大家好&#xff0c;我是闲鹤&#xff0c;公众号 xxh_zone&#xff0c;十多年开发、架构经验&#xff0c;先后在华为、迅雷服役过&#xff0c;也在高校从事教学3年&#xff1b;目前已创业了7年多&a…

UML交互图-协作图

概述 协作图和序列图都表示出了对象间的交互作用&#xff0c;但是它们侧重点不同。序列图清楚地表示了交互作用中的时间顺序&#xff0c;但没有明确表示对象间的关系。协作图则清楚地表示了对象间的关系&#xff0c;但时间顺序必须从顺序号获得。序列图常常用于表示方案&#…

使用紫铜管制作半波天线的折合振子

一、概述 半波天线是一种简单而有效的天线类型&#xff0c;其长度约为工作波长的一半。它具有较好的辐射特性和较高的增益&#xff0c;广泛应用于业余无线电、电视接收等领域。使用紫铜管制作折合振子&#xff0c;不仅可以提高天线的机械强度&#xff0c;还能增强其导电性能。 …

k8s——Pod容器中的存储方式及PV、PVC

一、Pod容器中的存储方式 需要存储方式前提&#xff1a;容器磁盘上的文件的生命周期是短暂的&#xff0c;这就使得在容器中运行重要应用时会出现一些问题。 首先&#xff0c;当容器崩溃时&#xff0c;kubelet 会重启它&#xff0c;但是容器中的文件将丢失——容器以干净的状态&…

如何让tracert命令的显示信息显示*星号

tracert命令如果在中间某一个节点超时&#xff0c;只会在显示信息中标识此节点信息超时“ * * * ”&#xff0c;不影响整个tracert命令操作。 如上图所示&#xff0c;在DeviceA上执行tracert 10.1.2.2命令&#xff0c;缺省情况下&#xff0c;DeviceA上的显示信息为&#xff1a;…