4 前缀和、双端队列使用:子串

news2024/11/24 14:58:48

很多方法需要借助数据结构来操作;

1 数组

2 栈

3 队列

4 堆

5 链表

        双端队列(deque,全称为double-ended queue)是一种特殊的线性数据结构,它允许在其两端进行添加和删除操作。在Python中,双端队列由标准库collections模块提供,类名为collections.deque。相比于列表,双端队列在两端执行插入和删除操作时更加高效,特别是对于大量数据的插入和删除操作,因为deque的底层实现是基于双向链表的,保证了这些操作的时间复杂度为O(1)。

双端队列因其高效的插入和删除特性,在多种场景下非常有用:

  • 队列和栈: 可以当作先进先出(FIFO)的队列使用(使用appendpopleft),也可以作为后进先出(LIFO)的栈使用(使用appendpop)。
  • 滑动窗口: 在处理数组或序列问题时,如计算连续子数组的最大和、滑动平均等,deque可以方便地维持一个固定大小的窗口。
  • 浏览器导航: 实现浏览器的前进和后退功能,其中前进历史可以用右侧添加,后退历史用左侧添加,通过popleftpop来模拟用户操作。
  • 表达式求值: 解析表达式时,可以使用deque来存储操作符栈。

总之,Python中的collections.deque是一个灵活且高效的数据结构,特别适合那些需要频繁在两端进行插入和删除操作的应用场景。

https://leetcode.cn/problems/subarray-sum-equals-k/

1 560. 和为 K 的子数组

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。子数组是数组中元素的连续非空序列。

示例 1:

输入:nums = [1,1,1], k = 2
输出:2

示例 2:
输入:nums = [1,2,3], k = 3
输出:2
关键字: 连续子数组的和;
前缀和: 从前面某一个位置数据到当前位置的总和;
一个连续子数组的和 = 两个前缀和的差;

有点动态规划的影子。

1 设定一个字典用:到目前访问a这个下标,之前有多少个这样的前缀子串。

 K :V,  K 是到目前为止的前缀和, V:有多少个这样的前缀和

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        dict_cum = defaultdict(int)
        dict_cum[0] = 1
        # 前缀和
        cum_nums = 0
        res = 0
        for i,num in enumerate(nums):
            cum_nums += num

            # 想一下 dict_cum[cum_nums - k]: 到目前为止的所有前缀和;
            res += dict_cum.get(cum_nums-k,0)

            dict_cum[cum_nums] = dict_cum.get(cum_nums,0) + 1

        return res

2 239. 滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

示例 2:

输入:nums = [1], k = 1
输出:[1]

2.1 暴力破解

1 遍历数组;

2 固定长度为K窗口,查找最大值;

时间复杂度 O(NK);超时;

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        slid_windows = nums[:k]
        max_list = [max(slid_windows)]
    
        for i in range(k,len(nums)):
            slid_windows.pop(0)
            slid_windows.append(nums[i])
            max_list.append(max(slid_windows))
        return max_list

2.2 双端队列方法

借助一个双端队列:队尾(left)保存之前 (小于)K 个最大值的排序;

队列功能:

1 保存索引;

2 队尾是当前访问的最大值; 这样每一次遍历数组中的元素,把队尾元素拿出来就是最大值了。

3 队是有序的(降序);

如何保证有序?

每次访问一个元素X,就从右到左访问队,如果队头小于X,弹出去;

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        ans = []
        q = deque()

        for i,x in enumerate(nums):

            # 保证降序
            while q and nums[q[-1]]<=x:
                q.pop()
            # 把当前的加入队中
            q.append(i)
            # 看一下 最大值 是不是已经过界了, 如果最大值在窗口最左边,窗口滑动了,这个元素就要弹出去
            if i - q[0] >= k:
                q.popleft()
            # 保存最大值
            if i - k >= -1:
                ans.append(nums[q[0]])
        return ans

3 76. 最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。

示例 2:

输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。

滑动窗口的心法(核心思想)

  1. 初始化双指针left和right。【初始化】
  2. 先不断增加right扩大窗口,直到窗口中的内容符合要求。【寻找可行解】
  3. 停止增加right,不断增加left缩小窗口,直到窗口中的内容不再满足要求。在每次增加left时都要更新所求的结果。【优化可行解】
  4. 不断重复扩大窗口、缩小窗口的操作,直到right到达序列的末端。
def slidingWindow(s:str,t:str):
    '''初始化 window 和 need 两个哈希表,记录窗口中的字符和需要凑齐的字符:'''
    need, window = collections.defaultdict(int), collections.defaultdict(int) # {char:int}
    for c in t:
        need[c] += 1
    left, right = 0, 0
    valid = 0 # 表示窗口中满足need条件的字符个数,如果valid和len(need)的大小相同,则说明窗口已满足条件
    '''使用 left 和 right 变量初始化窗口的两端,不要忘了,区间 [left, right) 是左闭右开的,所以初始情况下窗口没有包含任何元素:'''
    while right < len(s):
        # c是将要移入窗口的字符
        c = s[right]
        # 增大窗口
        right += 1
        # 进行窗口内数据的一系列更新
        ..."""更新窗口数据的地方"""

        # 判断左侧窗口是否要收缩
        while '''window needs shrink''':
            # d是将要移出窗口的字符
            d = s[left]
            # 缩小窗口
            left += 1
            # 进行窗口内数据的一系列更新
        	..."""更新窗口数据的地方"""
class Solution:
    def minWindow(self, s: str, t: str) -> str:

        patt_set = defaultdict(int)
        current_set = defaultdict(int)

        for c in t:
            patt_set[c]+=1
            
        need = 0
        # 最小开始, 长度
        start ,length = 0, sys.maxsize
        right ,left = 0, 0
        

        while right < len(s):
            c = s[right] 
            right += 1

            if c in patt_set:
                current_set[c] += 1
                if current_set[c]==patt_set[c]:
                    need+=1

            # 查看是否满足条件,然后让窗口不满足条件
            while need == len(patt_set):
                if right - left < length:
                    start = left
                    length = right - left
                
                # 缩小窗口
                
                c = s[left]
                #print(left,c, len(s), patt_set, current_set)
                left += 1
                if c in current_set:
                    if current_set[c] == patt_set[c]:
                        need -= 1
                    current_set[c] -= 1
        return "" if length==sys.maxsize else s[start: start+length]
            


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

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

相关文章

keil软件的一些使用技巧

1.MDK 的 TAB 键支持块操作 也就是可以让一片代码整体右移固定的几个位&#xff0c;也可以通过 SHIFTTAB 键整体左移固定的几个位。 2.快速注释与快速消注释 就是先选中你要注释的代码区&#xff0c;然后右键&#xff0c;选择Advanced→Comment Selection 就可以了。 3.快速打…

FFmpeg教程-三-播放pcm文件-1

目录 一&#xff0c;下载SDL 二&#xff0c;在Qt中测试 1&#xff0c;在pro文件中加入路径 2&#xff0c;在.cpp文件中加入头文件 3&#xff0c;进行测试 4&#xff0c;显示结果 一&#xff0c;下载SDL 通过编程的方式播放音视频&#xff0c;也是需要用到这2个库: FFmpeg…

百度智能云升级:接入33个大模型,Llama 2引领创新,103个Prompt模板上线

大家好&#xff0c;我是herosunly。985院校硕士毕业&#xff0c;现担任算法研究员一职&#xff0c;热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名&#xff0c;CCF比赛第二名&#xff0c;科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…

Mysql常用SQL:日期转换成周_DAYOFWEEK(date)

有时候需要将查询出来的日期转换成周几&#xff0c;Mysql本身语法就是支持这种转换的&#xff0c;就是DAYOFWEEK()函数 语法格式&#xff1a;DAYOFWEEK(date) &#xff08;date&#xff1a;可以是指定的具体日期&#xff08; 如2024-06-29 &#xff09;&#xff0c;也可以是日期…

pc端制作一个顶部固定的菜单栏

效果 hsl颜色 hsl颜色在css中比较方便 https://www.w3school.com.cn/css/css_colors_hsl.asp 色相&#xff08;hue&#xff09;是色轮上从 0 到 360 的度数。0 是红色&#xff0c;120 是绿色&#xff0c;240 是蓝色。饱和度&#xff08;saturation&#xff09;是一个百分比值…

数据可视化在智慧园区中的重要作用

在现代智慧园区的建设和管理中&#xff0c;数据的作用越来越重要。智慧园区利用物联网、云计算、大数据等技术&#xff0c;实现了园区各类信息的实时采集和处理。数据可视化作为数据处理和展示的重要工具&#xff0c;为智慧园区的各个方面提供了强有力的支持。 首先&#xff0c…

【AI提升】AI利器Tool Call/Function Call(一):langchain+ollama+llama3/qwen2

1、使用AI的一个常用场景就是&#xff0c;接收人类的语言&#xff0c;识别人类的意图&#xff0c;最终进行相关的业务处理&#xff0c;这就是设计Tool Call / Function Call的初衷。 2、现在一般都说Tool Call&#xff0c;以前常叫Function Call&#xff0c;不要纠结。 一、安…

【提交ACM出版 | EIScopus检索稳定 | 高录用】第五届大数据与社会科学国际学术会议(ICBDSS 2024,8月16-18)

第五届大数据与社会科学国际学术会议&#xff08;ICBDSS 2024&#xff09;将于2024年08月16-18日在中国-上海隆重举行。 ICBDSS会议在各专家教授的支持下&#xff0c;去年已成功举办了四届会议。为了让更多的学者有机会参与会议分享交流经验。本次会议主要围绕“大数据”、“社…

在线字节大端序小端序转换器

具体请前往&#xff1a;在线字节大端序小端序转换器

Linux kernel 与 设备树

Linux kernel 与 设备树 1 介绍1.1 概述1.2 发展历程1.3 各版本发布时间及特色1.4 Linux 单内核1.5 Linux 内核网址1.6 NXP 官方镜像与 野火 鲁班猫镜像的区别 2 Linux 内核组成2.1 进程管理2.2 内存管理2.3 文件系统2.4 设备管理2.5 网络功能 3 Linux 内核编译3.1 编译 Kernel…

Linux上使用 git 命令行

在 Github或者 gitee 注册账号 这个比较简单 , 参考着官网提示即可 . 需要进行邮箱校验.以下以创建Github为例。 创建项目 1. 登陆成功后 , 进入个人主页 , 点击下方的 create a new repository 按钮新建项目 2. 在创建好的项目页面中复制项目的链接 , 以备接下来进行下…

pandas数据分析(1)

pandas&#xff0c;即Python数据分析库&#xff08;Python data analysis library&#xff09; DataFrame和Series DataFrame&#xff08;数据帧&#xff09;和Series&#xff08;序列&#xff09;是pandas的核心数据结构。DataFrame的主要组件包含索引、列、数据。DataFrame和…

使用matlab开发stm32总结,stm32-matlab常见的问题处理以及报错合集

1&#xff0c;问题&#xff1a;本来是好的&#xff0c;突然编译运行报错&#xff0c;说是确少包&#xff0c; 解决方案&#xff1a;重启以后好了 2&#xff0c;有完美的马鞍波&#xff0c;为什么不能够转动呢&#xff1f; 原因是我这里模型的问题&#xff0c;我计算出来的是占…

访客(UV)、点击量(PV)、IP、访问量(VV)概念

1、https://www.cnblogs.com/QingPingZm/articles/13855808.htmlhttps://www.cnblogs.com/QingPingZm/articles/13855808.html

不能创建第三个变量,实现两个数的交换

目录 常规实现两个数的交换&#xff08;如&#xff1a;交换变量a和变量b&#xff09; 方法一&#xff1a;加减法 方法二&#xff1a;异或操作符 常规实现两个数的交换&#xff08;如&#xff1a;交换变量a和变量b&#xff09; 创建一个临时变量tmp&#xff0c;先将其中一个…

Java代码基础算法练习-计算被 3 或 5 整除数之和-2024.06.29

任务描述&#xff1a; 计算 1 到 n 之间能够被 3 或者 5 整除的数之和。 解决思路&#xff1a; 输入的数字为 for 循环总次数&#xff0c;每次循环就以当前的 i 进行 3、5 的取余操作&#xff0c;都成立计入总数sum中&#xff0c;循环结束&#xff0c;输出 sum 的值 代码示例&…

MySQL高级-SQL优化- order by 优化(尽量使用覆盖索引、注意联合索引创建的规则、增大排序缓冲区大小)

文章目录 0、order by优化原则1、Using filesort2、Using index3、连接数据库4、查看索引5、删除索引6、按照年龄进行排序7、执行计划 order by age8、执行计划 order by age,phone9、创建联合索引 (age,phone)10、再次执行计划 order by age11、再次执行计划 order by age,pho…

仓库管理系统18--出库管理

原创不易&#xff0c;打字不易&#xff0c;截图不易&#xff0c;多多点赞&#xff0c;送人玫瑰&#xff0c;留有余香&#xff0c;财务自由明日实现。 1、创建用户控件OutStoreView <UserControl x:Class"West.StoreMgr.View.OutStoreView"xmlns"http://sche…

C++【函数重载】【附有C语言为何不能实现函数重载的讲解】

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;LiUEEEEE                        …

【股指期权投教】一手股指期权大概多少钱?

一手股指期权的权利金大概在几千人民币左右&#xff0c;如果是作为期权卖方还需要另外缴纳保证金的。国内的股指期权有三种&#xff0c;沪深300、上证50、中证1000股指期权&#xff0c;每点合约人民币100 元。 期权合约的价值计算可以通过此公式得出&#xff1a;权利金的支付或…