1652. Defuse the Bomb
Problem Description
You need to defuse a bomb by decrypting a circular array code
of length n
using a key k
.
The decryption process replaces every number in the array simultaneously based on these rules:
- If
k > 0
: Replace thei
-th number with the sum of the nextk
numbers - If
k < 0
: Replace thei
-th number with the sum of the previous|k|
numbers - If
k == 0
: Replace thei
-th number with0
Since the array is circular:
- The next element after
code[n-1]
iscode[0]
- The previous element before
code[0]
iscode[n-1]
For example, if code = [5,7,1,4]
and k = 3
:
- For index 0: sum the next 3 elements →
7 + 1 + 4 = 12
- For index 1: sum the next 3 elements →
1 + 4 + 5 = 10
(wraps around) - For index 2: sum the next 3 elements →
4 + 5 + 7 = 16
(wraps around) - For index 3: sum the next 3 elements →
5 + 7 + 1 = 13
(wraps around) - Result:
[12, 10, 16, 13]
The solution iterates through each position i
in the array:
- When
k > 0
: It calculatesans[i] = sum(code[(i+1) % n] to code[(i+k) % n])
- When
k < 0
: It calculatesans[i] = sum(code[(i+k) % n] to code[(i-1) % n])
The modulo operator %
handles the circular nature of the array, ensuring indices wrap around correctly.
Intuition
The key insight is recognizing that this is a straightforward simulation problem where we need to handle circular array indexing properly.
Since we need to replace all numbers simultaneously, we can't modify the original array in-place. We need a separate result array to store the new values. This ensures that when calculating the sum for position i
, we're always using the original values, not the already-replaced ones.
For the circular nature of the array, we can use the modulo operator %
to wrap around indices. When we go past the end of the array (index >= n), the modulo operation brings us back to the beginning. For example, if we have an array of length 4 and we're at index 3, the next index would be (3 + 1) % 4 = 0
, which correctly wraps to the start.
The three cases are handled separately:
- When
k = 0
, every element becomes 0 - this is trivial - When
k > 0
, we sum the nextk
elements by iterating fromi+1
toi+k
and usingj % n
to handle wrapping - When
k < 0
, we sum the previous|k|
elements by iterating fromi+k
(which is negative offset) toi-1
, and using(j + n) % n
to handle negative indices properly
The reason we add n
in the negative case is to convert negative indices to their positive equivalents. For instance, index -1
should map to n-1
(the last element), and (-1 + n) % n = n-1
achieves this.
The time complexity is O(n * |k|)
since for each of the n
positions, we sum up |k|
values. The space complexity is O(n)
for the result array.
Learn more about Sliding Window patterns.
Solution Approach
The implementation follows a simulation approach where we process each position in the array and calculate its new value based on the given rules.
First, we initialize an answer array ans
of length n
with all zeros. This serves as our result array where we'll store the decrypted values.
If k = 0
, we immediately return the ans
array since all elements should be replaced with 0.
For non-zero values of k
, we iterate through each position i
from 0 to n-1
:
When k > 0:
- We need to sum the next
k
elements after positioni
- We iterate from
i + 1
toi + k
(inclusive) - For each position
j
in this range, we addcode[j % n]
toans[i]
- The modulo operation
j % n
handles the circular wrapping whenj >= n
The mathematical formula is:
ans[i] = Σ(j=i+1 to i+k) code[j mod n]
When k < 0:
- We need to sum the previous
|k|
elements before positioni
- We iterate from
i + k
toi - 1
(inclusive) - Since
k
is negative,i + k
gives us the starting position|k|
positions beforei
- For each position
j
in this range, we addcode[(j + n) % n]
toans[i]
- Adding
n
before taking modulo ensures we handle negative indices correctly
The mathematical formula is:
ans[i] = Σ(j=i+k to i-1) code[(j + n) mod n]
The key technique here is using modular arithmetic to handle the circular array:
j % n
maps any indexj >= n
back into the valid range[0, n-1]
(j + n) % n
maps negative indices to their positive equivalents (e.g.,-1
becomesn-1
)
After processing all positions, we return the ans
array containing the decrypted values.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a small example with code = [2, 4, 9, 3]
and k = -2
.
Since k = -2
(negative), we need to replace each element with the sum of the previous 2 elements.
Initial Setup:
n = 4
(length of array)- Create
ans = [0, 0, 0, 0]
to store results
Processing each position:
Position i = 0:
- Need to sum previous 2 elements: positions from
(0 + (-2)) = -2
to(0 - 1) = -1
- For
j = -2
:(-2 + 4) % 4 = 2
, so we addcode[2] = 9
- For
j = -1
:(-1 + 4) % 4 = 3
, so we addcode[3] = 3
ans[0] = 9 + 3 = 12
Position i = 1:
- Need to sum previous 2 elements: positions from
(1 + (-2)) = -1
to(1 - 1) = 0
- For
j = -1
:(-1 + 4) % 4 = 3
, so we addcode[3] = 3
- For
j = 0
:(0 + 4) % 4 = 0
, so we addcode[0] = 2
ans[1] = 3 + 2 = 5
Position i = 2:
- Need to sum previous 2 elements: positions from
(2 + (-2)) = 0
to(2 - 1) = 1
- For
j = 0
:(0 + 4) % 4 = 0
, so we addcode[0] = 2
- For
j = 1
:(1 + 4) % 4 = 1
, so we addcode[1] = 4
ans[2] = 2 + 4 = 6
Position i = 3:
- Need to sum previous 2 elements: positions from
(3 + (-2)) = 1
to(3 - 1) = 2
- For
j = 1
:(1 + 4) % 4 = 1
, so we addcode[1] = 4
- For
j = 2
:(2 + 4) % 4 = 2
, so we addcode[2] = 9
ans[3] = 4 + 9 = 13
Final Result: [12, 5, 6, 13]
The circular array behavior is clearly demonstrated at position 0, where we wrap around to access elements at the end of the array (indices 2 and 3).
Solution Implementation
1class Solution:
2 def decrypt(self, code: List[int], k: int) -> List[int]:
3 """
4 Decrypts a circular array based on the value of k.
5
6 Args:
7 code: List of integers representing the circular array
8 k: Integer determining the decryption pattern
9 - If k > 0: Replace each element with sum of next k elements
10 - If k < 0: Replace each element with sum of previous |k| elements
11 - If k == 0: Replace all elements with 0
12
13 Returns:
14 List of integers representing the decrypted array
15 """
16 n = len(code)
17 result = [0] * n # Initialize result array with zeros
18
19 # If k is 0, all elements become 0
20 if k == 0:
21 return result
22
23 # Process each position in the array
24 for i in range(n):
25 if k > 0:
26 # Sum the next k elements (wrapping around using modulo)
27 for j in range(i + 1, i + k + 1):
28 result[i] += code[j % n]
29 else: # k < 0
30 # Sum the previous |k| elements (wrapping around using modulo)
31 for j in range(i + k, i):
32 result[i] += code[(j + n) % n]
33
34 return result
35
1class Solution {
2 /**
3 * Decrypts a circular array based on the given key k.
4 * - If k > 0: Replace each element with sum of next k elements
5 * - If k < 0: Replace each element with sum of previous |k| elements
6 * - If k = 0: Replace all elements with 0
7 *
8 * @param code The input circular array to decrypt
9 * @param k The decryption key determining direction and count
10 * @return The decrypted array
11 */
12 public int[] decrypt(int[] code, int k) {
13 int arrayLength = code.length;
14 int[] result = new int[arrayLength];
15
16 // If k is 0, return array filled with zeros
17 if (k == 0) {
18 return result;
19 }
20
21 // Process each element in the array
22 for (int currentIndex = 0; currentIndex < arrayLength; currentIndex++) {
23 if (k > 0) {
24 // Sum the next k elements (circular)
25 for (int offset = 1; offset <= k; offset++) {
26 int circularIndex = (currentIndex + offset) % arrayLength;
27 result[currentIndex] += code[circularIndex];
28 }
29 } else {
30 // Sum the previous |k| elements (circular)
31 for (int offset = k; offset < 0; offset++) {
32 // Add arrayLength to handle negative indices correctly
33 int circularIndex = (currentIndex + offset + arrayLength) % arrayLength;
34 result[currentIndex] += code[circularIndex];
35 }
36 }
37 }
38
39 return result;
40 }
41}
42
1class Solution {
2public:
3 vector<int> decrypt(vector<int>& code, int k) {
4 int n = code.size();
5 vector<int> result(n, 0); // Initialize result array with zeros
6
7 // If k is 0, all elements should be replaced with 0
8 if (k == 0) {
9 return result;
10 }
11
12 // Process each position in the circular array
13 for (int i = 0; i < n; ++i) {
14 if (k > 0) {
15 // Sum the next k elements (moving forward in circular array)
16 for (int j = i + 1; j <= i + k; ++j) {
17 result[i] += code[j % n]; // Use modulo for circular indexing
18 }
19 } else {
20 // Sum the previous |k| elements (moving backward in circular array)
21 for (int j = i + k; j < i; ++j) {
22 result[i] += code[(j % n + n) % n]; // Handle negative indices with modulo
23 }
24 }
25 }
26
27 return result;
28 }
29};
30
1/**
2 * Decrypts a circular array based on the given key k
3 * @param code - The array of numbers to decrypt
4 * @param k - The decryption key determining how many elements to sum
5 * @returns The decrypted array
6 */
7function decrypt(code: number[], k: number): number[] {
8 const arrayLength: number = code.length;
9 const result: number[] = Array(arrayLength).fill(0);
10
11 // If k is 0, all elements become 0
12 if (k === 0) {
13 return result;
14 }
15
16 // Process each element in the array
17 for (let currentIndex = 0; currentIndex < arrayLength; ++currentIndex) {
18 if (k > 0) {
19 // For positive k, sum the next k elements
20 for (let j = currentIndex + 1; j < currentIndex + k + 1; ++j) {
21 // Use modulo to handle circular array wrapping
22 result[currentIndex] += code[j % arrayLength];
23 }
24 } else {
25 // For negative k, sum the previous |k| elements
26 for (let j = currentIndex + k; j < currentIndex; ++j) {
27 // Add arrayLength before modulo to handle negative indices
28 result[currentIndex] += code[(j + arrayLength) % arrayLength];
29 }
30 }
31 }
32
33 return result;
34}
35
Time and Space Complexity
The time complexity of this code is O(n × |k|)
, where n
is the length of the input array code
and |k|
is the absolute value of k
.
This is because:
- The outer loop iterates through all
n
elements of the array - For each element
i
, the inner loop runs exactly|k|
times:- When
k > 0
: the loop runs fromi + 1
toi + k + 1
, which isk
iterations - When
k < 0
: the loop runs fromi + k
toi
, which is|k|
iterations
- When
- Each iteration of the inner loop performs a constant time operation (addition and modulo)
The space complexity is O(1)
if we exclude the space used for the output array ans
. The only additional space used is for the loop variables i
and j
, which require constant space regardless of the input size.
If we include the output array, the total space complexity would be O(n)
since ans
has the same length as the input array.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Handling of Negative Indices
The Pitfall:
When k < 0
, developers often forget to handle negative indices properly when wrapping around the circular array. Simply using j % n
for negative values of j
won't work correctly in most programming languages.
For example, if i = 0
and k = -2
, the range would be from -2
to -1
. Using -1 % n
in Python gives n-1
(which is correct), but in many other languages like Java or C++, -1 % n
returns -1
, causing an array index out of bounds error.
Incorrect approach:
# This might fail in other languages or cause confusion
for j in range(i + k, i):
result[i] += code[j % n] # Risky with negative j values
The Solution:
Always add n
before taking the modulo to ensure positive indices:
for j in range(i + k, i):
result[i] += code[(j + n) % n] # Safe for negative indices
2. Off-by-One Errors in Range Calculation
The Pitfall:
Developers might incorrectly calculate the range endpoints, especially forgetting that Python's range()
is exclusive of the end value.
Common mistakes:
# Mistake 1: Including current element when k > 0
for j in range(i, i + k): # Wrong! Includes code[i]
result[i] += code[j % n]
# Mistake 2: Wrong endpoint when k > 0
for j in range(i + 1, i + k): # Wrong! Missing one element
result[i] += code[j % n]
The Solution:
Ensure the range correctly excludes the current element and includes exactly k
elements:
# Correct: sum exactly k elements after position i
for j in range(i + 1, i + k + 1): # i+1 to i+k inclusive
result[i] += code[j % n]
3. Not Handling the k = 0 Case Early
The Pitfall:
Forgetting to handle k = 0
as a special case can lead to unnecessary computation or incorrect logic in the main loop.
The Solution:
Always check for k = 0
first and return immediately:
if k == 0: return [0] * n # Early return with all zeros
4. Using the Wrong Modulo Formula
The Pitfall:
Mixing up when to use j % n
versus (j + n) % n
can lead to incorrect results or runtime errors.
Rule of thumb:
- Use
j % n
whenj
is guaranteed to be non-negative - Use
(j + n) % n
whenj
might be negative - For extra safety, you can always use
(j % n + n) % n
which works for both positive and negative values
Universal safe approach:
def safe_mod(j, n):
return (j % n + n) % n
# Then use it consistently:
result[i] += code[safe_mod(j, n)]
Depth first search is equivalent to which of the tree traversal order?
Recommended Readings
https assets algo monster cover_photos stack svg Sliding Window Maximum Monotonic Stack We have an array and a sliding window defined by a start index and an end index The sliding window moves from left of the array to right There are always k elements in the window The window
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!