力扣2653.滑动窗口的美丽值

devtools/2024/10/21 15:15:15/

给你一个长度为 n 的整数数组 nums ,请你求出每个长度为 k 的子数组的 美丽值 。

一个子数组的 美丽值 定义为:如果子数组中第 x 小整数 是 负数 ,那么美丽值为第 x 小的数,否则美丽值为 0 。

请你返回一个包含 n - k + 1 个整数的数组,依次 表示数组中从第一个下标开始,每个长度为 k 的子数组的 美丽值 。

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

示例 1:

输入:nums = [1,-1,-3,-2,3], k = 3, x = 2
输出:[-1,-2,-2]
解释:总共有 3 个 k = 3 的子数组。
第一个子数组是 [1, -1, -3] ,第二小的数是负数 -1 。
第二个子数组是 [-1, -3, -2] ,第二小的数是负数 -2 。
第三个子数组是 [-3, -2, 3] ,第二小的数是负数 -2 。

示例 2:

输入:nums = [-1,-2,-3,-4,-5], k = 2, x = 2
输出:[-1,-2,-3,-4]
解释:总共有 4 个 k = 2 的子数组。
[-1, -2] 中第二小的数是负数 -1 。
[-2, -3] 中第二小的数是负数 -2 。
[-3, -4] 中第二小的数是负数 -3 。
[-4, -5] 中第二小的数是负数 -4 。

示例 3:

输入:nums = [-3,1,2,-3,0,-3], k = 2, x = 1
输出:[-3,0,-3,-3,-3]
解释:总共有 5 个 k = 2 的子数组。
[-3, 1] 中最小的数是负数 -3 。
[1, 2] 中最小的数不是负数,所以美丽值为 0 。
[2, -3] 中最小的数是负数 -3 。
[-3, 0] 中最小的数是负数 -3 。
[0, -3] 中最小的数是负数 -3 。

提示:

  • n == nums.length 
  • 1 <= n <= 105
  • 1 <= k <= n
  • 1 <= x <= k 
  • -50 <= nums[i] <= 50 

class Solution:def getSubarrayBeauty(self, nums: List[int], k: int, x: int) -> List[int]:cnt = [0] * 101  # 用于统计窗口内数值的频率
为什么用一个长度为 101 的数组 cnt
  • 范围映射:题目要求找负数,并且数组 nums 的取值范围为 [-50, 50]。为了高效统计每个元素在窗口内的频率,我们使用了一个大小为 101 的数组 cnt
    • 索引映射cnt[0] 对应数值 -50cnt[100] 对应数值 50,所有值都可以通过偏移量 50 映射到数组中的索引位置。
    • 频率数组的好处:使用频率数组,可以在 O(1) 时间复杂度内增减数值的频率。

        for num in nums[:k - 1]:  # 先往窗口添加 k-1 个数cnt[num + 50] += 1
为什么先预处理前 k-1 个数?
  • 这样可以为后续的滑动窗口 节省计算时间。窗口初始化时,我们先将前 k-1 个元素加入 cnt 频率数组中,这样在处理第一个完整窗口时,只需再加入第 k 个元素即可开始计算。

  • num + 50

    • 由于数组中的元素范围是 [-50, 50],我们将每个元素加上 50,映射到频率数组中的正确位置。

        ans = [0] * (len(nums) - k + 1)  # 初始化结果数组
为什么结果数组长度是 len(nums) - k + 1
  • 每个长度为 k 的窗口会对应一个美丽值,因此结果数组的长度是 len(nums) - k + 1

        for i, (in_, out) in enumerate(zip(nums[k-1:], nums)):cnt[in_ + 50] += 1  # 新元素进入窗口期
为什么使用 zip 和更新频率?
  • 滑动窗口
    • 使用 zip(nums[k-1:], nums) 遍历数组时,in_进入窗口的元素out离开窗口的元素
    • 当一个新元素进入窗口时,我们更新其频率:cnt[in_ + 50] += 1

            left = x  # 需要找到第 x 小的负数for j in range(-50, 0):  # 枚举负数范围 [-50, -1]left -= cnt[j + 50]  # 减去当前负数 j 的频率if left <= 0:  # 如果找到了第 x 小的负数ans[i] = j  # 记录美丽值break
为什么在负数范围 [-50, -1] 中查找?
  • 美丽值要求找到 x 小的负数,因此我们只需要遍历负数的范围 [-50, -1]。
  • 如何找到第 x 小的负数?
    • 使用一个计数变量 left,初始值为 x
    • 遍历每个负数 j 的频率 cnt[j + 50]。每次找到一个符合条件的负数时,将其频率从 left 中减去。
    • 一旦 left <= 0,说明我们已经找到了第 x 小的负数,并将其记录到 ans[i] 中。

  
 

            cnt[out + 50] -= 1  # 离开窗口的元素频率减 1
为什么离开窗口的元素需要减 1?
  • 保持窗口内元素的正确频率
    • 当一个元素离开窗口时,我们需要在频率数组中减去它的出现次数,确保下一个窗口的频率统计是准确的。
        return ans  # 返回结果数组
完整代码
class Solution:def getSubarrayBeauty(self, nums: List[int], k: int, x: int) -> List[int]:cnt = [0]*101for num in nums[:k-1]:      #先往窗口添加n个数cnt[num] += 1ans = [0]*(len(nums)-k+1)for i,(in_,out) in enumerate(zip(nums[k-1:],nums)): #建立滑动窗口cnt[in_] += 1 #进入窗口期  left = xfor j in range(-50,0):  #暴力枚举负数范围[-50,-1]left -=cnt[j]if left<= 0: #找到美丽值ans[i] = jbreakcnt[out] -= 1 #离开窗口return ans

举例:

运行步骤
  1. 初始化窗口
    k-1 个元素 [-1, -2] 被添加到频率数组中:

    cnt[-1 + 50] = 1 # cnt[49] = 1 cnt[-2 + 50] = 1 # cnt[48] = 1 
  2. 第一个窗口 [ -1, -2, 3 ]

    • 新元素 3 加入窗口,频率数组更新:cnt[53] = 1
    • 在负数范围 [-50, -1] 中查找第 2 小的负数:
      • 负数 -2 出现 1 次,left = 2 - 1 = 1
      • 负数 -1 出现 1 次,left = 1 - 1 = 0
      • 找到第 2 小的负数为 -1,记录 ans[0] = -1
  3. 第二个窗口 [ -2, 3, -1 ]

    • 新元素 -1 加入窗口,频率数组更新:cnt[49] = 2
    • 负数 -2-1 都出现了,最终记录的美丽值仍然是 -2

http://www.ppmy.cn/devtools/127591.html

相关文章

Android Studio简易项目|随机选择器(类似转盘)

一、背景 为了强化对flowlayout流式布局的理解和简易安卓项目架构结构的理解&#xff0c;写一个小项目&#xff0c;随机选择器&#xff0c;控制可见等 二、项目代码 2.1流式布局 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns…

10.19 RHCSA 作业

关闭防火墙&#xff0c;挂载&#xff0c;安装nginx用nmtui命令配置多ip ip a检测配置是否正确 vim /etc/nginx/conf.d/test ip.conf 配置nginx服务信息 在网站中添加内容 浏览器上测试网页内容

支持国密算法的数字证书-国密SSL证书详解

在互联网中&#xff0c;数字证书作为标志通讯各方身份信息的数字认证而存在&#xff0c;常见的数字证书大都采用国际算法&#xff0c;比如RSA算法、ECC算法、SHA2算法等。随着我国加强网络安全技术自主可控的大趋势&#xff0c;也出现了支持国密算法的数字证书-国密SSL证书。那…

Java的建造师:类和对象是什么?

在Java的世界里&#xff0c;类和对象就像建筑蓝图和实际的房子。类是用来设计和描述某种事物的模板&#xff0c;而对象就是根据这个模板建造出来的实际事物。咱可以把类看成是一张说明书&#xff0c;而对象是根据说明书创建出来的“产品”。 什么是类&#xff1f; 类&#xff…

Spark 基础概念

Apache Spark 是一个快速、分布式的计算系统&#xff0c;用于大规模数据处理和分析。它提供了一个高级 API&#xff0c;用于编写并行处理的任务&#xff0c;可以在大规模集群上运行。 Spark 的基本概念包括以下几个方面&#xff1a; Resilient Distributed Datasets (RDDs)&a…

RISC计算机 CISC计算机

复杂指令集系统与精简指令集系 在计算机系统结构发展的过程中&#xff0c; 指令系统的优化设计有两个截然相反的方向&#xff0c; 一个是增强指令的功能&#xff0c; 设置一些功能复杂的指令&#xff0c; 把一些原来由软件实现的、 常用的功能改用硬件的指令系统来实现&#xf…

Vue main.js引入全局changePassword组件原型实例,修改密码组件原型实例

main.js引入全局changePassword组件原型实例 changePassword 实例1. changePassword.vue2. proto.js 引入及使用main.jslogin.js main.js引入全局组件原型实例 changePassword 实例 1. changePassword.vue <template><el-dialog title"修改密码" :visibl…

​​【项目建设PPT模板】中台建设,中台设计,数字中台整体建设方案(PPT)

工业互联网数字中台解决方案旨在为企业提供全面、高效的数据驱动能力。该方案主要包括以下几个核心部分&#xff1a; 数据中台&#xff1a;作为核心&#xff0c;数据中台负责汇聚、整合、提纯和加工各类工业数据&#xff0c;实现数据资产的标准化、模型化和模块化。通过提供API…