JavaInterview JavaInterview
首页
指南
分类
标签
归档
  • CSDN (opens new window)
  • 文档集合 (opens new window)
  • 系统架构 (opens new window)
  • 微信号 (opens new window)
  • 公众号 (opens new window)

『Java面试+Java学习』
首页
指南
分类
标签
归档
  • CSDN (opens new window)
  • 文档集合 (opens new window)
  • 系统架构 (opens new window)
  • 微信号 (opens new window)
  • 公众号 (opens new window)
  • 指南
  • 简历

  • Java

  • 面试

  • 算法

  • algorithm
  • leetcode
JavaInterview.cn
2025-07-13
目录

1652. 拆炸弹Java

文章发布较早,内容可能过时,阅读注意甄别。

# 题目

你有一个炸弹需要拆除,时间紧迫!你的情报员会给你一个长度为 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

# 思路

一个套了定长滑窗的解密游戏!!!

# 解法

class Solution {
/**
     * 10 拆炸弹 1652
     * 分析:
     * 这题是一个套了定长滑窗的解密题
     * 这里比较新颖的一点是数组是“循环数组”
     * 看一看题目的解密规则:
     * 若 k == 0,那么解密后的结果全是0,特殊处理一下即可。
     * 若 k > 0,那么code[i] 要被替换为接下来的k个数字之和【包括i自己么?看了下示例是不包括的】
     *  k < 0就无需多盐了。
     * 并且通过观察示例我发现是基于code计算新code,因此开新数组是没得跑了。
     * 思路大概理清楚了,接下开开始干代码咯咯咯咯~
     */
    public int[] decrypt(int[] code, int k) {
        int n = code.length;
        if(n == 1 && k != 0){
            // 盐豆不盐了
            return code;
        }
        int[] newCode = new int[n];
        if(k == 0){
            // 盐豆不盐了
            return newCode;
        }
        // 特殊情况过滤完毕
        // 如何初始化窗口?
        /*
            从code[0]开始
            Ⅰ 若k > 0,那么left = 1【这就是为什么我要提前排除n == 1的原因】,right则要从left开始往右走k步(注意循环数组边界),期间收集统计量【窗口内元素和】
            Ⅱ 若k < 0,那么right = 0,然后left从right开始往左走|k|步,期间收集统计量。

            之后就简单了,code[0]的下一个code[1],只需要让窗口整体右移一位。
         */

        // 初始化窗口
        int left, right;
        // 统计量
        int sum = 0;
        if(k > 0){
            // 按照Ⅰ的流程初始化窗口
            right = left = 1;
            while (k-- > 0){
                // 让循环体执行k次就够了
                sum += code[right];
                // 循环数组下标右移的核心公式
                right = (right + 1) % n;
            }
        }else {
            // 按照Ⅱ的流程初始化窗口
            left = right = 0;
            while (k++ < 0){
                // 让循环体执行k次就够了
                // 循环数组下标左移的核心公式,建议自己推一遍
                left = (left - 1 + n) % n;
                sum += code[left];
            }
        }
        // 开始解密
        for (int i = 0; i < n; i++) {
            newCode[i] = sum;
            sum += code[right];
            right = (right + 1) % n;
            sum -= code[left];
            left = (left + 1) % n;
        }
        return newCode;
    }
}

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

# 总结

  • 分析出几种情况,然后分别对各个情况实现
微信 支付宝
#Java
最近更新
01
1633. 各赛事的用户注册率 Java
07-13
02
1636. 按照频率将数组升序排序 Java
07-13
03
1640. 能否连接形成数组 Java
07-13
更多文章>
Theme by Vdoing | Copyright © 2019-2025 JavaInterview.cn
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式