【定长滑动窗口】【刷题笔记】

ops/2024/11/22 8:46:20/

标题:《2841. 几乎唯一子数组的最大和问题解析》

在本文中,我们将深入探讨力扣上的 2841. 几乎唯一子数组的最大和这一问题,并详细解析两种不同的解答思路。

一、题目描述

给定一个整数数组 nums 和两个正整数 mk。要求返回 nums 中长度为 k 的几乎唯一子数组的最大和,如果不存在几乎唯一子数组,则返回 0。这里,如果 nums 的一个子数组有至少 m 个互不相同的元素,我们称它是几乎唯一子数组。子数组指的是一个数组中一段连续非空的元素序列。

二、解答思路

(一)第一种解答思路

以下是代码实现:

from typing import List
from collections import Counter
class Solution:def maxSum(self, nums: List[int], m: int, k: int) -> int:ans = 0s = sum(nums[:k - 1])  # 先统计 k - 1 个数cnt = Counter(nums[:k - 1])for out, in_ in zip(nums, nums[k - 1:]):s += in_  # 再添加一个数就是 k 个数了cnt[in_] += 1if len(cnt) >= m:ans = max(ans, s)s -= out  # 下一个子数组不包含 out,移出窗口cnt[out] -= 1if cnt[out] == 0:del cnt[out]return ans
  1. 整体思路
    • 首先计算初始窗口(前 k - 1 个数)的和 s 以及使用 Counter 统计这 k - 1 个数中每个数出现的次数,存储在 cnt 中。
    • 然后通过滑动窗口的方式,利用 zip 函数同时遍历原数组 nums 和从第 k - 1 个位置开始的子数组 nums[k - 1:]。在每次滑动时,将新进入窗口的数加入和 s 中,并更新 cnt 计数器,接着判断当前窗口内不同元素的数量是否满足至少 m 个,如果满足则更新最大和 ans。之后将离开窗口的数从和 s 中减去,并更新 cnt 计数器,如果该数的计数变为 0,则从 cnt 中删除该元素。
  2. 涉及的 Python 语法知识点
    • CounterCountercollections 模块中的一个类,它是一个字典的子类,用于方便地统计可迭代对象中每个元素出现的次数。例如,Counter([1, 2, 2, 3]) 会返回一个 Counter 对象 {1: 1, 2: 2, 3: 1},其中键是元素,值是该元素出现的次数。在本题中,它用于统计窗口内元素的出现次数,以便判断不同元素的数量是否满足条件。
    • zipzip 函数用于将多个可迭代对象中对应的元素打包成一个个元组,然后返回一个由这些元组组成的可迭代对象。在本题中,for out, in_ in zip(nums, nums[k - 1:]) 的作用是同时遍历原数组 nums 和从第 k - 1 个位置开始的子数组 nums[k - 1:],在每次循环中,out 是即将离开窗口的元素,in_ 是新进入窗口的元素,这样可以方便地进行窗口的滑动操作并处理相关逻辑。

(二)第二种解答思路

以下是代码实现:

from typing import List
class Solution:def maxSum(self, nums: List[int], m: int, k: int) -> int:n = len(nums)ans = 0      # 最终答案 几乎唯一(m 个互异元素)子数组(k 长度)的最大值sum_num = 0  # 当前窗口(当前子数组)加和cnt = {}     # 定义字典作为计数器,记录窗口内有无重复# 初始化窗口for i in range(k - 1):sum_num += nums[i]  # 计算加和if nums[i] in cnt:  # 字典计数器cnt[nums[i]] += 1else:cnt[nums[i]] = 1# 滑动窗口,for i in range(k - 1, n):# 1.进入窗口(本次操作前,窗口长度差一格)sum_num += nums[i]  # 加和if nums[i] in cnt:     # 字典计数器,cnt[nums[i]] += 1   # 当前元素出现过,cnt 字典长度不变,对应键值对改变else:                    # 没出现过,cnt 字典长度加 1cnt[nums[i]] = 1# 2.更新答案,前提是满足几乎唯一,也就是至少有 m 个互异元素if len(cnt) >= m:         # cnt 长度>=mans = max(ans, sum_num)# 3.(谁?i -(k - 1)位置的元素)退出窗口,out = nums[i - k + 1]   # 就是它退出了!sum_num -= out          # 先加和中去掉它cnt[out] -= 1           # 计数器中扣掉 1if cnt[out] == 0:del cnt[out]       # 如果扣完变成了 0,del 删掉字典中这个元素return ans
  1. 整体思路
    • 先初始化一个长度为 k - 1 的窗口,计算其和 sum_num 并统计窗口内元素出现次数到字典 cnt 中。
    • 接着进行滑动窗口操作,在每次循环中,先将新元素加入窗口,更新和 sum_num 与计数器 cnt。然后判断当前窗口内不同元素数量是否满足至少 m 个,如果满足则更新最大和 ans。最后将离开窗口的元素从和 sum_num 中减去,并更新计数器 cnt,若该元素计数变为 0,则从 cnt 中删除。

三、总结

两种解答思路都采用了滑动窗口的方法来解决问题。第一种思路借助了 Counterzip 等 Python 内置工具和函数,使得代码更加简洁高效,在统计元素出现次数和处理窗口滑动时更加方便。第二种思路则是较为传统的手动实现窗口内元素计数和窗口滑动操作,虽然代码相对第一种略显繁琐,但逻辑更加直观,有助于深入理解滑动窗口算法以及相关数据结构(如字典)在算法中的应用。在实际编程中,可以根据具体情况选择合适的方法来解决类似问题。

希望通过本文的解析,读者能够对 2841. 几乎唯一子数组的最大和这一问题有更深入的理解,并能熟练掌握滑动窗口算法以及相关 Python 语法知识在算法中的应用。

2461.长度为k子数组中的最大和

给你一个整数数组 nums 和一个整数 k 。请你从 nums 中满足下述条件的全部子数组中找出最大子数组和:

子数组的长度是 k,且
子数组中的所有元素 各不相同 。
返回满足题面要求的最大子数组和。如果不存在子数组满足这些条件,返回 0 。

子数组 是数组中一段连续非空的元素序列。

这题比上一题还简单!
class Solution:def maximumSubarraySum(self, nums: List[int], k: int) -> int:n = len(nums)ans = 0sum_num = 0cnt = {}for i in range(n):# 1.进入窗口sum_num += nums[i]       # 加和if nums[i] in cnt:       # 调用当前窗口,每个元素数量记录器cntcnt[nums[i]] += 1else:cnt[nums[i]] = 1    # 出现新元素,cnt长度加1if i < k - 1:           # 如果i没到k-1,也就是窗口长度没够时continue# 2.更新答案        # 前提是cnt长度与子数组长度k相等!表示当前窗口所有元素各不相同!if len(cnt) == k:ans = max(ans, sum_num)# 3.退出窗口       # 谁?i-(k-1)  # 加和删掉该位置元素  # 记录器删掉一次该元素!out = nums[i - k + 1]sum_num -= outcnt[out] -= 1if cnt[out] == 0:del cnt[out]return ans

http://www.ppmy.cn/ops/135736.html

相关文章

洛谷P1597

语句解析 - 洛谷 语句解析 题目背景 木有背景…… 题目描述 一串长度不超过255的 PASCAL 语言代码&#xff0c;只有 a,b,c 三个变量&#xff0c;而且只有赋值语句&#xff0c;赋值只能是一个一位的数字或一个变量&#xff0c;每条赋值语句的格式是 [变量]:[变量或一位整数…

【java-Neo4j 5开发入门篇】-最新Java开发Neo4j

系列文章目录 前言 上一篇文章讲解了Neo4j的基本使用&#xff0c;本篇文章对Java操作Neo4j进行入门级别的阐述&#xff0c;方便读者快速上手对Neo4j的开发。 一、开发环境与代码 1.docker 部署Neo4j #这里使用docker部署Neo4j,需要镜像加速的需要自行配置 docker run --name…

云原生基础-云计算概览

目录 云计算的基本概念 云计算的服务模型 云计算的部署模式 云计算的基本概念 云计算是一种通过互联网提供计算资源和服务的模式。允许用户按需访问和使用各种计算资源&#xff0c;如服务器、存储、数据库、网络等&#xff0c;而无需了解底层基础设施的具体细节。云计算的核心理…

AI数字人视频小程序:引领未来互动新潮流

当下&#xff0c;随着人工智能技术的不断创新发展&#xff0c;各类AI系统已经成为了创新市场发展的重要力量&#xff0c;AI文案、AI数字人、AI视频等&#xff0c;为大众带来更加便捷的创作方式&#xff0c;AI成为了一个全新的风口&#xff0c;各种AI红利持续释放&#xff0c;市…

大数据新视界 -- 大数据大厂之 Impala 性能优化:集群资源动态分配的智慧(上)(23 / 30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

优化算法|基于Deep-Q-Network(DQN)的邻域搜索算法求解分布式柔性作业车间调度问题

问题描述 分布式柔性作业车间调度&#xff08;Distributed FJSP&#xff0c;DFJSP&#xff09;主要包含工序序列、机器的选择和工厂的选择三个子问题。首先将&#x1d45b;个工件分配到不同的工厂当中&#xff0c;然后在每个工厂为工件选择可加工的机器以及确定工件的加工顺序…

鸿蒙NEXT开发案例:简体繁体转换器

【引言】 简体繁体转换器是一个实用的小工具&#xff0c;它可以帮助用户轻松地在简体中文和繁体中文之间进行转换。对于需要频繁处理两岸三地文档的用户来说&#xff0c;这样的工具无疑是提高工作效率的好帮手。本案例将展示如何利用鸿蒙NEXT提供的组件和服务&#xff0c;结合…

Stable Diffusion概要讲解

&#x1f33a;系列文章推荐&#x1f33a; 扩散模型系列文章正在持续的更新&#xff0c;更新节奏如下&#xff0c;先更新SD模型讲解&#xff0c;再更新相关的微调方法文章&#xff0c;敬请期待&#xff01;&#xff01;&#xff01;&#xff08;本文及其之前的文章均已更新&…