当前位置: 首页 > news >正文

LeetCode 1652. 拆炸弹

题目链接

1652. 拆炸弹

题目描述

给定一个长度为 n循环数组 code 和一个密钥 k,需要替换数组中的每个数字:

  • k > 0:第 i 个数字替换为接下来 k 个数字的和;
  • k < 0:第 i 个数字替换为之前 k 个数字的和;
  • k = 0:所有数字替换为 0

数组是循环的,即 code[n-1] 的下一个元素是 code[0]code[0] 的前一个元素是 code[n-1]

解法分析:滑动窗口法

核心思路

该解法通过滑动窗口技术高效计算循环数组中连续 k 个元素的和,核心步骤如下:

  1. 特殊处理 k=0 的情况(直接返回全0数组);
  2. 根据 k 的正负确定初始窗口的范围(k>0 取后续元素,k<0 取前置元素);
  3. 初始化窗口和,通过滑动窗口动态更新和(减去离开窗口的元素,加上进入窗口的元素);
  4. 利用取模操作处理循环数组的边界,确保索引合法。

代码实现

from typing import Listclass Solution:def decrypt(self, code: List[int], k: int) -> List[int]:n = len(code)ans = [0] * n  # 结果数组# 若k=0,直接返回全0数组if k == 0:return ans# 确定初始窗口的右边界r# k>0时:窗口为i的后续k个元素,初始右边界r = k + 1# k<0时:窗口为i的前置k个元素,初始右边界r = n(循环数组的特殊处理)r = k + 1 if k > 0 else nk_abs = abs(k)  # 统一窗口长度为k的绝对值# 初始化窗口和:窗口为[r - k_abs, r)(左闭右开)s = sum(code[r - k_abs : r])# 滑动窗口计算每个位置的结果for i in range(n):ans[i] = s  # 当前窗口和即为ans[i]的值# 更新窗口和:减去离开窗口的元素,加上进入窗口的新元素# 利用取模处理循环数组的边界s += code[r % n] - code[(r - k_abs) % n]r += 1  # 窗口右移return ans

代码解析

  1. 变量初始化

    • n:数组长度;
    • ans:结果数组,初始化为全0;
    • r:窗口的右边界(用于确定窗口范围),根据 k 的正负动态设置;
    • k_absk 的绝对值,统一窗口长度(无论 k 正负,窗口大小都是 |k|)。
  2. 特殊情况处理

    • k = 0,直接返回全0数组(题目要求)。
  3. 初始窗口和计算

    • 窗口范围为 [r - k_abs, r)(左闭右开),即包含 k_abs 个元素;
    • k > 0 时,r = k + 1,窗口初始为 code[1...k](对应第0个元素的后续 k 个元素);
    • k < 0 时,r = n,窗口初始为 code[n + k ... n - 1](对应第0个元素的前置 |k| 个元素,因 k 为负,n + k = n - |k|)。
  4. 滑动窗口逻辑

    • 遍历每个索引 i,将当前窗口和 s 赋值给 ans[i]
    • 更新窗口和:
      • 加上新进入窗口的元素 code[r % n]r 右移后,新元素的索引为 r % n,处理循环边界);
      • 减去离开窗口的元素 code[(r - k_abs) % n](窗口左边界的元素,同样用取模处理边界);
    • r += 1:窗口整体右移,继续计算下一个位置的结果。

关键逻辑说明

  • 窗口范围定义:采用左闭右开区间 [r - k_abs, r) 定义窗口,便于滑动时的边界计算(右移时只需更新 r 即可)。
  • 循环数组处理:通过 % n 操作确保索引始终在 [0, n-1] 范围内,完美适配循环数组的首尾相连特性。
  • 统一逻辑:无论 k 为正或负,均通过调整初始 r 的值实现窗口的正确定位,后续滑动逻辑完全一致,简化代码。

复杂度分析

  • 时间复杂度O(n),其中 n 是数组长度。初始化窗口和需 O(k_abs) 时间,滑动窗口遍历 n 次,每次操作 O(1),总复杂度 O(n + k_abs)。由于 k_abs ≤ n-1(题目隐含约束),故等价于 O(n)
  • 空间复杂度O(1),结果数组 ans 占用 O(n) 空间,其他变量为常数级。

示例详解

示例1:code = [5,7,1,4], k = 3k > 0

  • n = 4k_abs = 3k > 0r = 3 + 1 = 4
  • 初始窗口为 [4 - 3, 4) = [1, 4),对应 code[1:4] = [7,1,4],和 s = 7 + 1 + 4 = 12
循环ians[i]窗口更新(s)r变化
i=012s += code[4%4=0] - code[(4-3)%4=1] → 12 + 5 - 7 = 10r=5
i=110s += code[5%4=1] - code[(5-3)%4=2] → 10 + 7 - 1 = 16r=6
i=216s += code[6%4=2] - code[(6-3)%4=3] → 16 + 1 - 4 = 13r=7
i=313s += code[7%4=3] - code[(7-3)%4=0] → 13 + 4 - 5 = 12r=8

最终 ans = [12,10,16,13],与示例一致。

示例2:code = [1,2,3,4,5,6,7], k = -3k < 0

  • n = 7k_abs = 3k < 0r = 7
  • 初始窗口为 [7 - 3, 7) = [4,7),对应 code[4:7] = [5,6,7](第0个元素的前3个元素),和 s = 5 + 6 + 7 = 18
循环ians[i]窗口更新(s)r变化
i=018s += code[7%7=0] - code[(7-3)%7=4] → 18 + 1 - 5 = 14r=8
i=114s += code[8%7=1] - code[(8-3)%7=5] → 14 + 2 - 6 = 10r=9
i=210s += code[9%7=2] - code[(9-3)%7=6] → 10 + 3 - 7 = 6r=10

最终结果符合“每个元素为其前3个元素和”的要求。

总结

该解法通过滑动窗口技术和循环数组的取模处理,高效解决了问题,核心优势在于:

  1. 逻辑统一:通过调整初始窗口位置,将 k > 0k < 0 的情况合并处理,代码简洁;
  2. 高效滑动:窗口更新仅需 O(1) 时间,避免重复计算,总复杂度 O(n)
  3. 边界处理:利用左闭右开区间和取模操作,完美适配循环数组的特性,无边界错误。

该思路是处理“循环数组中连续元素和”问题的经典模板,可推广到类似场景(如循环数组的最大子数组和等)。

http://www.lryc.cn/news/584274.html

相关文章:

  • 二分查找篇——寻找旋转排序数组中的最小值【LeetCode】
  • 节点小宝:手机图片备份至电脑功能实测体验
  • 机器学习12——支持向量机中
  • Ubuntu 20.04 下**安装 FFmpeg 5.1
  • Lua嵌入式爬虫实现步骤
  • Redis性能基准测试
  • 观众信息设置与统计(视频高级分析与统计功能)
  • Windows下VScode配置FFmpeg开发环境保姆级教程
  • vue中token的使用与统计实践
  • 机器学习11——支持向量机上
  • 快速合并多个CAD图形为单一PDF文档的方法
  • 机器学习之逻辑回归和k-means算法(六)
  • 机器学习:反向神经元传播公式推导
  • C#基础:Winform桌面开发中窗体之间的数据传递
  • 机器学习13——支持向量机下
  • Linux - firewall 防火墙
  • Spring MVC 1
  • C语言<数据结构-链表>
  • 基于Catboost算法的茶叶数据分析及价格预测系统的设计与实现
  • CH9121T电路及配置详解
  • 《Stata面板数据分析:数据检验、回归模型与诊断技术 - 以NLSW工资研究(公开数据)为例》
  • 时间显示 蓝桥云课Java
  • 数据分析中的拉链表解析
  • 整数反转(C++)
  • JDK的Closure闭包详解
  • x86汇编语言入门基础(三)汇编指令篇3 位移运算
  • expect 安装入门手册
  • window显示驱动开发—XR_BIAS 和 BltDXGI
  • 图书管理系统(完结版)
  • windows11桌面部分区域无法点击