Skip to content

Files

Latest commit

fa73a73 · Jan 16, 2024

History

History

1652.Defuse the Bomb

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Jan 16, 2024
Jan 16, 2024
Jan 13, 2024
Jan 13, 2024
Jan 13, 2024
Jan 13, 2024
Sep 24, 2022
Jan 13, 2024
Jan 13, 2024
Jan 13, 2024
Jan 13, 2024

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

解法

方法一:模拟

定义答案数组 ans,长度为 n ,初始时所有元素都为 0 。根据题意,若 k 0 ,直接返回 ans

否则,遍历每个位置 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 )

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
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;
    }
}
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;
    }
};
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
}
function decrypt(code: number[], k: number): number[] {
    const n = code.length;
    if (k === 0) {
        return code.fill(0);
    }
    const isPrefix = k < 0;
    if (isPrefix) {
        k *= -1;
    }
    const map = new Map<number, [number, number]>();
    let prefix = 0;
    let suffix = 0;
    for (let i = 1; i <= k; i++) {
        prefix += code[n - i];
        suffix += code[i];
    }
    map.set(0, [prefix, suffix]);

    for (let i = 1; i < n; i++) {
        let [p, s] = map.get(i - 1);
        p -= code[n - k - 1 + i] ?? code[i - k - 1];
        p += code[i - 1];
        s -= code[i];
        s += code[i + k] ?? code[i + k - n];
        map.set(i, [p, s]);
    }
    for (let i = 0; i < n; i++) {
        code[i] = map.get(i)[Number(!isPrefix)];
    }
    return code;
}

方法二:前缀和

在方法一中,对于每个位置 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 数组的长度。

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
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;
    }
}
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;
    }
};
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
}