1652.拆炸弹

【LetMeFly】1652.拆炸弹:滑动窗口——当个简单的中等题做

力扣题目链接:https://leetcode.cn/problems/defuse-the-bomb/

你有一个炸弹需要拆除,时间紧迫!你的情报员会给你一个长度为 n 的 循环 数组 code 以及一个密钥 k 。

为了获得正确的密码,你需要替换掉每一个数字。所有数字会 同时 被替换。

  • 如果 k > 0 ,将第 i 个数字用 接下来 k 个数字之和替换。
  • 如果 k < 0 ,将第 i 个数字用 之前 k 个数字之和替换。
  • 如果 k == 0 ,将第 i 个数字用 0 替换。

由于 code 是循环的, code[n-1] 下一个元素是 code[0] ,且 code[0] 前一个元素是 code[n-1] 。

给你 循环 数组 code 和整数密钥 k ,请你返回解密后的结果来拆除炸弹!

 

示例 1:

输入:code = [5,7,1,4], k = 3
输出:[12,10,16,13]
解释:每个数字都被接下来 3 个数字之和替换。解密后的密码为 [7+1+4, 1+4+5, 4+5+7, 5+7+1]。注意到数组是循环连接的。

示例 2:

输入:code = [1,2,3,4], k = 0
输出:[0,0,0,0]
解释:当 k 为 0 时,所有数字都被 0 替换。

示例 3:

输入:code = [2,4,9,3], k = -2
输出:[12,5,6,13]
解释:解密后的密码为 [3+9, 2+3, 4+2, 9+4] 。注意到数组是循环连接的。如果 k 是负数,那么和为 之前 的数字。

 

提示:

  • n == code.length
  • 1 <= n <= 100
  • 1 <= code[i] <= 100
  • -(n - 1) <= k <= n - 1

解题方法:滑动窗口

滑动窗口

若$k=0$,则不在本次讨论范围内,直接返回全$0$数组即可。

先计算出answer[0]的值,使用两个变量lr分别记录answer[0]的“求和范围”:

  • 若$k\gt 0$,则answer[0]的“求和范围”是l = 1, r = k
  • 否则($k\lt 0$),answer[0]的“求和范围”是l = n - (-k), r = n - 1

现在,你有办法根据answer[0]的结果,快速求出answer[1]的结果吗?

当然,新的“求和范围”是l' = (l + 1) mod n, r' = (r + 1) mod n

因此,只需要在answer[0]的基础上,减去一个code[l]并加上一个code[r']就好了。

以此类推,后面每个答案的值都能在上一个答案的基础上在$O(1)$时间内求得。这就是滑动窗口

  • 时间复杂度$O(n)$
  • 空间复杂度$O(1)$,力扣返回值不计入算法空间复杂度

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Solution {
private:
int n;

inline int next(int i) {
return (i + 1) % n;
}

public:
vector<int> decrypt(vector<int>& code, int k) {
n = code.size();
vector<int> ans(n);
if (!k) {
return ans;
}
int l, r, s = 0; // left, right, sum
if (k > 0) { // [1, k]
l = 1;
for (r = l; r <= k; r++) {
s += code[r];
}
r--;
}
else { // [n - (-k), n - 1]
r = n - 1;
for (l = r; l >= n + k; l--) {
s += code[l];
}
l++;
}
for (int i = 0; i < n; i++) {
ans[i] = s;
s -= code[l];
l = next(l);
r = next(r);
s += code[r];
}
return ans;
}
};

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# from typing import List

class Solution:
def next(self, i: int) -> int:
return (i + 1) % self.n

def decrypt(self, code: List[int], k: int) -> List[int]:
self.n = len(code)
ans = [0] * self.n
if not k:
return ans
l, r, s = 0, 0, 0
if k > 0:
l = 1
for r in range(l, k + 1):
s += code[r]
else:
r = self.n - 1
for l in range(r, self.n + k - 1, -1):
s += code[l]
for i in range(self.n):
ans[i] = s
s -= code[l]
l = self.next(l)
r = self.next(r)
s += code[r]
return ans

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/138465984


1652.拆炸弹
https://blog.letmefly.xyz/2024/05/05/LeetCode 1652.拆炸弹/
作者
Tisfy
发布于
2024年5月5日
许可协议