Skip to content

Files

Latest commit

c29b144 · May 17, 2024

History

History
This branch is 1 commit ahead of, 1191 commits behind doocs/leetcode:main.

1652.Defuse the Bomb

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
May 17, 2024
May 17, 2024
Jan 13, 2024
Jan 13, 2024
Jan 13, 2024
Jan 13, 2024
May 5, 2024
Jan 13, 2024
Jan 13, 2024
Jan 13, 2024
Jan 13, 2024
May 5, 2024
comments difficulty edit_url rating source tags
true
简单
1416
第 39 场双周赛 Q1
数组
滑动窗口

English Version

题目描述

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

解法

方法一:模拟

我们定义一个长度为 n 的答案数组 a n s ,初始时所有元素都为 0 。根据题意,若 k 0 ,直接返回 a n s

否则,遍历每个位置 i

k 为正数,那么 i 位置的值为 i 位置后 k 个位置的值之和,即:

a n s [ i ] = j = i + 1 i + k c o d e [ j mod n ]

k 为负数,那么 i 位置的值为 i 位置前 | k | 个位置的值之和,即:

a n s [ i ] = j = i + k i 1 c o d e [ ( j + n ) mod n ]

时间复杂度 O ( n × | k | ) ,忽略答案的空间消耗,空间复杂度 O ( 1 )

Python3

class Solution:
    def decrypt(self, code: List[int], k: int) -> List[int]:
        n = len(code)
        ans = [0] * n
        if k == 0:
            return ans
        for i in range(n):
            if k > 0:
                for j in range(i + 1, i + k + 1):
                    ans[i] += code[j % n]
            else:
                for j in range(i + k, i):
                    ans[i] += code[(j + n) % n]
        return ans

Java

class Solution {
    public int[] decrypt(int[] code, int k) {
        int n = code.length;
        int[] ans = new int[n];
        if (k == 0) {
            return ans;
        }
        for (int i = 0; i < n; ++i) {
            if (k > 0) {
                for (int j = i + 1; j < i + k + 1; ++j) {
                    ans[i] += code[j % n];
                }
            } else {
                for (int j = i + k; j < i; ++j) {
                    ans[i] += code[(j + n) % n];
                }
            }
        }
        return ans;
    }
}

C++

class Solution {
public:
    vector<int> decrypt(vector<int>& code, int k) {
        int n = code.size();
        vector<int> ans(n);
        if (k == 0) {
            return ans;
        }
        for (int i = 0; i < n; ++i) {
            if (k > 0) {
                for (int j = i + 1; j < i + k + 1; ++j) {
                    ans[i] += code[j % n];
                }
            } else {
                for (int j = i + k; j < i; ++j) {
                    ans[i] += code[(j + n) % n];
                }
            }
        }
        return ans;
    }
};

Go

func decrypt(code []int, k int) []int {
	n := len(code)
	ans := make([]int, n)
	if k == 0 {
		return ans
	}
	for i := 0; i < n; i++ {
		if k > 0 {
			for j := i + 1; j < i+k+1; j++ {
				ans[i] += code[j%n]
			}
		} else {
			for j := i + k; j < i; j++ {
				ans[i] += code[(j+n)%n]
			}
		}
	}
	return ans
}

TypeScript

function decrypt(code: number[], k: number): number[] {
    const n: number = code.length;
    const ans: number[] = Array(n).fill(0);

    if (k === 0) {
        return ans;
    }

    for (let i = 0; i < n; ++i) {
        if (k > 0) {
            for (let j = i + 1; j < i + k + 1; ++j) {
                ans[i] += code[j % n];
            }
        } else {
            for (let j = i + k; j < i; ++j) {
                ans[i] += code[(j + n) % n];
            }
        }
    }

    return ans;
}

方法二:前缀和

在方法一中,对于每个位置 i ,都需要遍历 k 个位置,有很多重复计算的操作。我们可以利用前缀和来优化。

我们将 code 数组复制一份(可以不用执行复制操作,直接通过循环遍历取模实现),得到两倍长度的数组,对其求前缀和,得到长度为 2 × n + 1 的前缀和数组 s

k 为正数,那么 i 位置的值为 i 位置后 k 个位置的值之和,即 a n s [ i ] = s [ i + k + 1 ] s [ i + 1 ]

k 为负数,那么 i 位置的值为 i 位置前 | k | 个位置的值之和,即 a n s [ i ] = s [ i + n ] s [ i + k + n ]

时间复杂度 O ( n ) ,空间复杂度 O ( n ) 。其中 n code 数组的长度。

Python3

class Solution:
    def decrypt(self, code: List[int], k: int) -> List[int]:
        n = len(code)
        ans = [0] * n
        if k == 0:
            return ans
        s = list(accumulate(code + code, initial=0))
        for i in range(n):
            if k > 0:
                ans[i] = s[i + k + 1] - s[i + 1]
            else:
                ans[i] = s[i + n] - s[i + k + n]
        return ans

Java

class Solution {
    public int[] decrypt(int[] code, int k) {
        int n = code.length;
        int[] ans = new int[n];
        if (k == 0) {
            return ans;
        }
        int[] s = new int[n << 1 | 1];
        for (int i = 0; i < n << 1; ++i) {
            s[i + 1] = s[i] + code[i % n];
        }
        for (int i = 0; i < n; ++i) {
            if (k > 0) {
                ans[i] = s[i + k + 1] - s[i + 1];
            } else {
                ans[i] = s[i + n] - s[i + k + n];
            }
        }
        return ans;
    }
}

C++

class Solution {
public:
    vector<int> decrypt(vector<int>& code, int k) {
        int n = code.size();
        vector<int> ans(n);
        if (k == 0) {
            return ans;
        }
        vector<int> s(n << 1 | 1);
        for (int i = 0; i < n << 1; ++i) {
            s[i + 1] = s[i] + code[i % n];
        }
        for (int i = 0; i < n; ++i) {
            if (k > 0) {
                ans[i] = s[i + k + 1] - s[i + 1];
            } else {
                ans[i] = s[i + n] - s[i + k + n];
            }
        }
        return ans;
    }
};

Go

func decrypt(code []int, k int) []int {
	n := len(code)
	ans := make([]int, n)
	if k == 0 {
		return ans
	}
	s := make([]int, n<<1|1)
	for i := 0; i < n<<1; i++ {
		s[i+1] = s[i] + code[i%n]
	}
	for i := range code {
		if k > 0 {
			ans[i] = s[i+k+1] - s[i+1]
		} else {
			ans[i] = s[i+n] - s[i+k+n]
		}
	}
	return ans
}

TypeScript

function decrypt(code: number[], k: number): number[] {
    const n: number = code.length;
    const ans: number[] = Array(n).fill(0);

    if (k === 0) {
        return ans;
    }

    const s: number[] = Array((n << 1) | 1).fill(0);
    for (let i = 0; i < n << 1; ++i) {
        s[i + 1] = s[i] + code[i % n];
    }

    for (let i = 0; i < n; ++i) {
        if (k > 0) {
            ans[i] = s[i + k + 1] - s[i + 1];
        } else {
            ans[i] = s[i + n] - s[i + k + n];
        }
    }

    return ans;
}