【专题刷题】滑动窗口(二):水果成篮,所有字母异位词,乘积小于 K 的子数组

news2025/7/20 2:07:43

📝前言说明:

  • 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录,按专题划分
  • 每题主要记录:(1)本人解法 + 本人屎山代码;(2)优质解法 + 优质代码;(3)精益求精,更好的解法和独特的思想(如果有的话)
  • 文章中的理解仅为个人理解。如有错误,感谢纠错

🎬个人简介:努力学习ing
📋本专栏:C++刷题专栏
📋其他专栏:C语言入门基础,python入门基础,C++学习笔记,Linux
🎀CSDN主页 愚润泽

视频

  • 904. 水果成篮
    • 个人解
    • 优质解:
  • LCR 015. 找到字符串中所有字母异位词
    • 个人解
    • 优质解:
  • 713. 乘积小于 K 的子数组
    • 个人解


904. 水果成篮

在这里插入图片描述
这道题题目容易让人产生歧义。但是通过示例就可以看出来,题目想表达的意思是:
不同数字代表不同类型的水果,求最长子数组,要求这个最长子数组中的不同的数字个数不超过2。

个人解

思路:滑动窗口+哈希表
把题目转换成最长子数组问题,用一个same变量标记子数组内不同的数字的个数。并且用一个map记录每个数字出现的次数。

  • 进窗口时,维护same(通过判断进入的是不是新数字)
  • 判断:因为是求最长,所以当不满足条件的时候才要出窗口
  • 出窗口:更新维护值same,并且出窗口后更新结果

用时:13:00
屎山代码:

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int n = fruits.size(), ans = 0, same = 2;
        std::map<int, int> cnt; // 记录每个数字出现的次数
        for(int left = 0, right = 0; right < n; right++)
        {
            cnt[fruits[right]]++; // 进窗口
            if(cnt[fruits[right]] == 1) // 代表是进窗口的是新数字
            {
                same--;
            }
            while(same < 0) // 判断
            {
                if(cnt[fruits[left]] == 1)
                {
                    same++; // 代表出窗口的数字是子数组中最后一个
                }
                cnt[fruits[left]]--; // 出窗口
                left++;
            }
            ans = max(ans, right - left + 1);
        }
    return ans;
    }
};

时间复杂度:O(n)
空间复杂度:O(1)


优质解:

思路:别人也是滑动窗口+哈希表,不过别人写的更简洁一点,更好的利用了map这个数据结构。(学习一下)
代码(来源:灵茶山艾府):

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int ans = 0, left = 0;
        unordered_map<int, int> cnt; // 比map更快
        for (int right = 0; right < fruits.size(); right++) {
            cnt[fruits[right]]++; // fruits[right] 进入窗口
            while (cnt.size() > 2) { // 直接用cnt.size()来反映子数组中不同数字的个数
                int out = fruits[left];
                cnt[out]--; // fruits[left] 离开窗口
                if (cnt[out] == 0) {
                    cnt.erase(out); // 当没有元素了,直接erase,会把键也删掉,呼应上面的cnt.size()
                }
                left++;
            }
            ans = max(ans, right - left + 1);
        }
        return ans;
    }
};

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

在这里插入图片描述

个人解

思路:
用哈希记录 p 串的每个字母出现的次数。
然后遍历字符串,将每一个和 p 串长度相同的子串的哈希表和 p 串的哈希表进行比较。当相同时就加入答案。
用时:20:00
屎山代码:

class Solution {
public:
    bool is_change(string s, map<char, int> dict_p)
    {
        map<char, int> dict_s;
        for(auto x: s)
        {
            dict_s[x]++;
        }
        for(auto x: dict_p)
        {
            if(x.second != dict_s[x.first])
            {
                return false;
            }
        }
        return true;
    }

    vector<int> findAnagrams(string s, string p) 
    {

        map<char, int> dict_p;
        for(auto x : p)
        {
            dict_p[x]++;
        }
        
        int len = p.size(), n = s.size();
        vector<int> ans;

        for(int left = 0, right = len - 1; right < n; right++, left++)
        {
            if(is_change(string(s.begin() + left, s.begin() + right + 1), dict_p))
            {
                ans.push_back(left);
            }
        }
        return ans;
    }
};

时间复杂度:O(nm),只想到了这个暴力(n是s的长度,m是p的长度,外层循环n次,内层每次比较都需要遍历一个m长度的子串,并且要遍历哈希表【哈希表的元素个数最多为26个】)
空间复杂度:O(dict.size() + ans.size())


优质解:

思路:

暴力解法中:遍历肯定是少不了的。通过比较哈希表来判断两个串是否是“异位词”也没办法变。那么能变的就是能不能减少每个子串的哈希表的获取的时间。
因为每次我们都是进入一个字母或者出去一个字母,所以我们只需要每次改变原来哈希表中的一个字母对应的次数就行了!
进窗口:hash2[s[right]]++
判断:窗口长度是否等于 p 的长度
出窗口:hash1[s[left]]--
更新结果:哈希表相同时

代码:

class Solution {
public:
    bool is_change(int* hash1, int* hash2) {
        for (int i = 0; i < 26; i++) {
            if (hash1[i] != hash2[i]) {
                return false;
            }
        }
        return true;
    }

    std::vector<int> findAnagrams(std::string s, std::string p) {
        std::vector<int> ans;
        int m = p.size(), n = s.size();
        if (n < m) return ans; // 如果 s 的长度小于 p,直接返回空结果

        int hash1[26] = { 0 }, hash2[26] = { 0 };
        for (auto ch : p) { // p 的哈希表
            hash1[ch - 'a']++;
        }

        for (int left = 0, right = 0; right < n; right++) {
            hash2[s[right] - 'a']++; // 新字符加入窗口
            if (right - left + 1 > m) {
                hash2[s[left] - 'a']--; // 窗口左边界右移,移除最左边字符
                left++;
            }
            if (right - left + 1 == m && is_change(hash1, hash2)) {
                ans.push_back(left); // 窗口大小等于 p 的长度且满足条件,记录起始索引
            }
        }

        return ans;
    }
};     

时间复杂度:O(n)
空间复杂度:O(26 + ans.size())


713. 乘积小于 K 的子数组

在这里插入图片描述

个人解

思路:越短越合法型滑动窗口

  • 进窗口:维护窗口内乘积mul
  • 判断:当窗口内乘积>=k时要出窗口
  • 出窗口:更新mul
  • 更新结果:因为出窗口后必然乘积<k

注意两个小点:

  1. nums[i]≥1,乘积不可能小于 1,所以当 k≤1 时,没有这样的子数组,直接返回 0
  2. 题目要求的是所有子数组,所以我们要考虑进窗口以后会新增哪些子数组?增加的就是(特有新增nums[right]的),即:以nums[right]为尾的往前长度增加的到nums[left]的这些子数组。

用时:10:00
屎山代码:

class Solution {
public:
    int numSubarrayProductLessThanK(vector<int>& nums, int k) {
        int ans = 0, mul = 1; 
        if(k <= 1){
            return 0;
        }
        for(int left = 0, right = 0; right < nums.size(); right++)
        {
            mul *= nums[right]; // 进窗口
            while(mul >= k)
            {
                mul /= nums[left++];
            }
            ans += right - left + 1;
        }
        return ans;
    }
};

时间复杂度:O(n)
空间复杂度:O(1)


🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

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

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

相关文章

深入理解React中的Props与State:核心区别与最佳实践

在React开发中&#xff0c;props和state是构建交互式UI的两大基石。许多React初学者常常混淆这两者的概念&#xff0c;导致组件设计出现反模式。本文将全面剖析props与state的本质区别&#xff0c;通过实际场景说明它们的适用边界&#xff0c;并分享高效管理组件数据的实践经验…

STM32单片机入门学习——第46节: [14-1] WDG看门狗

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难&#xff0c;但我还是想去做&#xff01; 本文写于&#xff1a;2025.04.23 STM32开发板学习——第46节: [14-1] WDG看门狗 前言开发板说明引用解答和科普一、…

n8n 中文系列教程_05.如何在本机部署/安装 n8n(详细图文教程)

n8n 是一款强大的开源工作流自动化工具&#xff0c;可帮助你连接各类应用与服务&#xff0c;实现自动化任务。如果你想快速体验 n8n 的功能&#xff0c;本机部署是最简单的方式。本教程将手把手指导你在 Windows 或 MacOS 上通过 Docker 轻松安装和运行 n8n&#xff0c;无需服务…

2025第十六届蓝桥杯python B组满分题解(详细)

目录 前言 A: 攻击次数 解题思路&#xff1a; 代码&#xff1a; B: 最长字符串 解题思路&#xff1a; 代码&#xff1a; C: LQ图形 解题思路&#xff1a; 代码&#xff1a; D: 最多次数 解题思路&#xff1a; 代码&#xff1a; E: A * B Problem 解题思路&…

Kafka 面试,java实战贴

面试问题列表 Kafka的ISR机制是什么&#xff1f;如何保证数据一致性&#xff1f; 如何实现Kafka的Exactly-Once语义&#xff1f; Kafka的Rebalance机制可能引发什么问题&#xff1f;如何优化&#xff1f; Kafka的Topic分区数如何合理设置&#xff1f; 如何设计Kafka的高可用跨…

linux多线(进)程编程——(9)信号量(一)

前言 在找到了共享内存存在的问题后&#xff0c;进程君父子着手开始解决这些问题。他们发明了一个新的神通——信号量。 信号量 信号量是一个计数器&#xff0c;用于管理对共享资源的访问权限。主要特点包括&#xff1a; &#xff08;1&#xff09;是一个非负整数 &#xff…

PFLM: Privacy-preserving federated learning with membership proof证明阅读

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目…

图片转base64 - 加菲工具 - 在线转换

图片转base64 - 加菲工具 先进入“加菲工具” 网 打开 https://www.orcc.top&#xff0c; 选择 “图片转base64”功能 选择需要转换的图片 复制 点击“复制”按钮&#xff0c;即可复制转换好的base64编码数据&#xff0c;可以直接用于img标签。

opencv 对图片的操作

对图片的操作 1.图片镜像旋转&#xff08;cv2.flip()&#xff09;2 图像的矫正 1.图片镜像旋转&#xff08;cv2.flip()&#xff09; 图像的旋转是围绕一个特定点进行的&#xff0c;而图像的镜像旋转则是围绕坐标轴进行的。图像的镜像旋转分为水平翻转、垂直翻转、水平垂直翻转…

LabVIEW数据采集与传感系统

开发了一个基于LabVIEW的智能数据采集系统&#xff0c;该系统主要通过单片机与LabVIEW软件协同工作&#xff0c;实现对多通道低频传感器信号的有效采集、处理与显示。系统的设计旨在提高数据采集的准确性和效率&#xff0c;适用于各种需要高精度和低成本解决方案的工业场合。 项…

【Easylive】​​Gateway模块 bootstrap.yml 解析

【Easylive】项目常见问题解答&#xff08;自用&持续更新中…&#xff09; 汇总版 Gateway模块 bootstrap.yml 常规解析 该配置文件定义了 Spring Cloud Gateway 的核心配置&#xff0c;包括 环境配置、服务注册、动态路由规则 等。以下是逐项解析&#xff1a; 1. 基础配…

matlab 环形单层柱状图

matlab 环形单层柱状图 matlab 环形单层柱状图 matlab 环形单层柱状图 图片 图片 【图片来源粉丝】 我给他的思路是&#xff1a;直接使用风玫瑰图可以画出。 rose_bar 本次我的更新和这个有些不同&#xff01;是环形柱状图&#xff0c;可调节细节多&#xff1b; 只需要函数…

文献×汽车 | 基于 ANSYS 的多级抛物线板簧系统分析

板簧系统是用于减弱或吸收动态系统中发生的应力、应变、偏转和变形等破坏性因素的机械结构。板簧系统可能对外力产生不同的响应&#xff0c;具体取决于其几何结构和材料特性。板簧系统的计算机辅助分析对于高精度确定系统的变形特性和结构特性至关重要。 在这项工作中&#xff…

RHCE 练习二:通过 ssh 实现两台主机免密登录以及 nginx 服务通过多 IP 区分多网站

一、题目要求 1.配置ssh实现A&#xff0c;B主机互相免密登录 2.配置nginx服务&#xff0c;通过多ip区分多网站 二、实验 实验开始前需准备两台 linux 主机便于充当服务端以及客户端&#xff0c;两台主机 IP 如下图&#xff1a; 实验1&#xff1a;配置 ssh 实现 A&#xff0…

瑞吉外卖-分页功能开发中的两个问题

1.分页功能-前端页面展示显示500 原因&#xff1a;项目启动失败 解决&#xff1a;发现是Category实体类中&#xff0c;多定义了一个删除字段&#xff0c;但是我数据库里面没有is_deleted字段&#xff0c;导致查询数据库失败&#xff0c;所以会导致500错误。因为类是从网上其他帖…

工业物联网安全网关 —— 安全OTA升级签名验证

这里写目录标题 工业物联网安全网关 —— 安全OTA升级签名验证一、项目背景与简介1.1 背景介绍1.2 OTA升级的安全挑战1.3 项目目标二、理论基础与关键技术2.1 数字签名基础2.2 OTA升级签名验证原理2.3 关键技术与安全算法三、系统架构设计3.1 系统模块划分3.2 系统架构图(Merm…

探索 Flowable 后端表达式:简化流程自动化

什么是后端表达式&#xff1f; 在 Flowable 中&#xff0c;后端表达式是一种强大的工具&#xff0c;用于在流程、案例或决策表执行期间动态获取或设置变量。它还能实现自定义逻辑&#xff0c;或将复杂逻辑委托…… 后端表达式在 Flowable 的后端运行&#xff0c;无法访问前端…

HDFS入门】HDFS安全与权限管理解析:从认证到加密的完整指南

目录 引言 1 认证与授权机制 1.1 Kerberos认证集成 1.2 HDFS ACL细粒度控制 2 数据加密保护 2.1 传输层加密(SSL/TLS) 2.2 静态数据加密 3 审计与监控体系 3.1 操作审计流程 3.2 安全监控指标 4 权限模型详解 4.1 用户/组权限模型 4.2 umask配置原理 5 安全最佳实…

性能比拼: Go vs Java

本内容是对知名性能评测博主 Anton Putra Go (Golang) vs Java: Performance Benchmark 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准 在本视频中&#xff0c;我们将比较 Go 和 Java。 我们将基于 Golang 的 Fiber 框架和 Java 的 Spring Boot 创建几个简单的应用…

ElMessageBox消息弹框(vue3总结)

一 展示各种内容 const checkCheckbox (check: any, formEl: any) > {ElMessageBox({title: "服务协议及隐私权政策",message: h("p", null, [h("span", null, "我已阅读并同意 "),h("span",{style: "color: #477F…