3379. Transformed Array
Problem Description
You have an integer array nums
that represents a circular array. You need to create a new array result
of the same size by following specific movement rules based on the values in nums
.
For each index i
in the array:
-
If
nums[i] > 0
: Starting from indexi
, movenums[i]
steps to the right in the circular array. The value at the landing position becomesresult[i]
. -
If
nums[i] < 0
: Starting from indexi
, moveabs(nums[i])
steps to the left in the circular array. The value at the landing position becomesresult[i]
. -
If
nums[i] == 0
: Simply setresult[i]
to 0 (which isnums[i]
).
The array is circular, meaning:
- Moving right past the last element wraps around to the beginning
- Moving left past the first element wraps around to the end
Each transformation at index i
is performed independently based on the original array nums
.
Example walkthrough:
If nums = [2, -1, 0, 3]
:
- At index 0:
nums[0] = 2
, move 2 steps right from index 0 → land at index 2 →result[0] = nums[2] = 0
- At index 1:
nums[1] = -1
, move 1 step left from index 1 → land at index 0 →result[1] = nums[0] = 2
- At index 2:
nums[2] = 0
, no movement →result[2] = 0
- At index 3:
nums[3] = 3
, move 3 steps right from index 3 → wrap around to index 2 →result[3] = nums[2] = 0
The solution uses the modulo operation (i + x + n) % n
to handle the circular nature of the array, where adding n
ensures the result is always positive before applying modulo.
Intuition
The key insight is recognizing that this is fundamentally an indexing problem with circular array navigation. Each element tells us how many steps to move and in which direction, and we need to find where we land.
For circular arrays, we need to handle wraparound when indices go out of bounds. The standard technique for this is using the modulo operator %
.
Let's think through the movement logic:
- Moving right from index
i
byx
steps means going to indexi + x
- Moving left from index
i
byx
steps means going to indexi - x
However, these simple additions/subtractions can give us indices outside the valid range [0, n-1]
. In a circular array:
- If we go past the end (index ≥ n), we wrap to the beginning
- If we go before the start (index < 0), we wrap to the end
The modulo operation % n
handles the wraparound naturally, but there's a subtle issue with negative numbers. In many programming languages, -1 % n
gives -1
, not n-1
as we'd want for array indexing.
To handle both positive and negative movements uniformly, we can use the formula: (i + x + n) % n
Why does this work?
- For positive
x
:(i + x + n) % n
=(i + x) % n
wheni + x ≥ 0
, which correctly wraps around - For negative
x
: Addingn
ensures the sum is positive before applying modulo, giving us the correct wrapped index - The extra
+ n
doesn't affect positive cases since(i + x + n) % n
=(i + x) % n
when the result fits in the array
This single formula elegantly handles all cases: moving right, moving left, and wraparound in both directions, making the implementation clean and concise.
Solution Approach
The implementation follows a straightforward simulation approach where we iterate through each index and compute its corresponding value in the result array.
Algorithm Steps:
-
Initialize the result array: Create an empty list
ans
to store the transformed values. -
Get array length: Store
n = len(nums)
for use in the modulo calculations. -
Iterate through each element: Use
enumerate(nums)
to get both the indexi
and valuex
at each position. -
Apply transformation rule for each element:
- If
x
is non-zero: Calculate the target index using(i + x + n) % n
- This formula handles both positive and negative movements
- The
+ n
ensures we always have a positive value before applying modulo
- If
x
is zero: Simply append 0 to the result
- If
-
Return the result: After processing all elements, return the completed
ans
array.
Implementation Details:
class Solution:
def constructTransformedArray(self, nums: List[int]) -> List[int]:
ans = []
n = len(nums)
for i, x in enumerate(nums):
ans.append(nums[(i + x + n) % n] if x else 0)
return ans
The solution uses a ternary operator for conciseness:
nums[(i + x + n) % n]
whenx
is non-zero (handles both positive and negative movements)0
whenx
is zero
Time Complexity: O(n)
where n is the length of the array. We iterate through each element exactly once.
Space Complexity: O(n)
for storing the result array. No additional auxiliary space is needed beyond the output.
The beauty of this solution lies in its simplicity - the circular array navigation is handled entirely by the modulo arithmetic (i + x + n) % n
, eliminating the need for conditional logic to handle different movement directions or boundary cases.
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 nums = [3, -2, 1, 0]
to illustrate the solution approach.
Initial Setup:
- Array length
n = 4
- We'll process each index independently using the formula
(i + x + n) % n
Step-by-step transformation:
Index 0: nums[0] = 3
- We need to move 3 steps to the right from index 0
- Target index =
(0 + 3 + 4) % 4 = 7 % 4 = 3
result[0] = nums[3] = 0
Index 1: nums[1] = -2
- We need to move 2 steps to the left from index 1
- Target index =
(1 + (-2) + 4) % 4 = 3 % 4 = 3
result[1] = nums[3] = 0
Index 2: nums[2] = 1
- We need to move 1 step to the right from index 2
- Target index =
(2 + 1 + 4) % 4 = 7 % 4 = 3
result[2] = nums[3] = 0
Index 3: nums[3] = 0
- No movement needed (value is 0)
result[3] = 0
Final result: [0, 0, 0, 0]
Key observations from this walkthrough:
- The formula
(i + x + n) % n
correctly handles positive movements (wrapping around when needed) - For negative movements, adding
n
ensures we get a positive number before applying modulo - When
x = 0
, we simply use 0 as the result - Each transformation is independent - we always reference the original
nums
array
Solution Implementation
1class Solution:
2 def constructTransformedArray(self, nums: List[int]) -> List[int]:
3 """
4 Constructs a transformed array based on the values in the input array.
5
6 For each element at index i with value x:
7 - If x > 0: take the element x positions to the right (with wraparound)
8 - If x < 0: take the element |x| positions to the left (with wraparound)
9 - If x == 0: set the result to 0
10
11 Args:
12 nums: Input list of integers
13
14 Returns:
15 Transformed list based on the rules above
16 """
17 result = []
18 n = len(nums)
19
20 # Iterate through each element in the input array
21 for i, value in enumerate(nums):
22 if value == 0:
23 # If value is 0, append 0 to result
24 result.append(0)
25 else:
26 # Calculate the target index with wraparound
27 # (i + value + n) % n handles both positive and negative offsets
28 # Adding n ensures the result is always positive before modulo
29 target_index = (i + value + n) % n
30 result.append(nums[target_index])
31
32 return result
33
1class Solution {
2 public int[] constructTransformedArray(int[] nums) {
3 // Get the length of the input array
4 int arrayLength = nums.length;
5
6 // Initialize the result array with the same length as input
7 int[] result = new int[arrayLength];
8
9 // Iterate through each index of the input array
10 for (int currentIndex = 0; currentIndex < arrayLength; currentIndex++) {
11 // Check if the current element is zero
12 if (nums[currentIndex] == 0) {
13 // If zero, the result at this index is also zero
14 result[currentIndex] = 0;
15 } else {
16 // Calculate the target index based on the current value
17 // Formula: (currentIndex + nums[currentIndex]) mod arrayLength
18 // Adding arrayLength before final mod ensures proper handling of negative values
19 int targetIndex = ((currentIndex + nums[currentIndex] % arrayLength + arrayLength) % arrayLength);
20
21 // Assign the value at the target index to the result array
22 result[currentIndex] = nums[targetIndex];
23 }
24 }
25
26 // Return the transformed array
27 return result;
28 }
29}
30
1class Solution {
2public:
3 vector<int> constructTransformedArray(vector<int>& nums) {
4 int n = nums.size();
5 vector<int> result(n);
6
7 for (int i = 0; i < n; ++i) {
8 if (nums[i] == 0) {
9 // If current element is 0, result at index i is 0
10 result[i] = 0;
11 } else {
12 // Calculate the target index with circular array handling
13 // (i + nums[i] % n + n) % n ensures proper wrapping for both positive and negative values
14 // - nums[i] % n: reduces the offset to within array bounds
15 // - + n: handles negative values to ensure positive result
16 // - final % n: wraps around if index exceeds array size
17 int targetIndex = (i + nums[i] % n + n) % n;
18 result[i] = nums[targetIndex];
19 }
20 }
21
22 return result;
23 }
24};
25
1/**
2 * Constructs a transformed array based on the input array's values.
3 * Each element in the result array is determined by using the current element's value
4 * as an offset to access another element in the input array.
5 *
6 * @param nums - The input array of numbers to transform
7 * @returns A new array where each element is transformed based on the rule
8 */
9function constructTransformedArray(nums: number[]): number[] {
10 // Get the length of the input array
11 const arrayLength: number = nums.length;
12
13 // Initialize the result array
14 const resultArray: number[] = [];
15
16 // Iterate through each element in the input array
17 for (let index = 0; index < arrayLength; ++index) {
18 // If current element is 0, push 0 to result
19 // Otherwise, calculate the target index using modular arithmetic
20 if (nums[index] === 0) {
21 resultArray.push(0);
22 } else {
23 // Calculate the target index:
24 // 1. Add current index with the value at current index
25 // 2. Apply modulo to handle negative values and wrap around
26 // 3. The formula (i + (nums[i] % n) + n) % n ensures proper circular indexing
27 const targetIndex: number = (index + (nums[index] % arrayLength) + arrayLength) % arrayLength;
28 resultArray.push(nums[targetIndex]);
29 }
30 }
31
32 return resultArray;
33}
34
Time and Space Complexity
Time Complexity: O(n)
- The code iterates through the input array
nums
exactly once usingenumerate(nums)
, which takesO(n)
time wheren
is the length of the array - Inside the loop, each operation is constant time:
- Checking if
x
is zero:O(1)
- Computing the index
(i + x + n) % n
:O(1)
- Accessing an element
nums[...]
:O(1)
- Appending to the result list:
O(1)
amortized
- Checking if
- Therefore, the overall time complexity is
O(n) * O(1) = O(n)
Space Complexity: O(n)
- The algorithm creates a new list
ans
to store the transformed array, which will contain exactlyn
elements - The variable
n
stores the length of the array:O(1)
- The loop variables
i
andx
use constant space:O(1)
- No additional data structures or recursive calls are used
- Therefore, the overall space complexity is
O(n)
for the output array
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Handling of Negative Modulo
The Pitfall:
Many programmers make the mistake of using (i + value) % n
directly without adding n
first. In Python, this can produce negative results when i + value
is negative, leading to incorrect array indexing.
Example of the Bug:
# INCORRECT implementation
def constructTransformedArray(self, nums):
result = []
n = len(nums)
for i, value in enumerate(nums):
if value == 0:
result.append(0)
else:
# Bug: This can produce negative indices!
target_index = (i + value) % n
result.append(nums[target_index])
return result
Why it fails:
- Consider
nums = [1, -3, 2]
at index 0 value = 1
, but if we were at index 1 withvalue = -3
(1 + (-3)) % 3 = -2 % 3 = -2
in Python- This gives us
nums[-2]
which is valid in Python but gives the wrong element (second from the end)
The Solution:
Always add n
before applying modulo to ensure a positive result:
target_index = (i + value + n) % n
This guarantees the index is in the range [0, n-1]
.
2. Modifying the Original Array During Iteration
The Pitfall:
Some might try to optimize by modifying nums
in-place while building the result, forgetting that all transformations should be based on the original array values.
Example of the Bug:
# INCORRECT implementation
def constructTransformedArray(self, nums):
n = len(nums)
for i in range(n):
if nums[i] != 0:
target_index = (i + nums[i] + n) % n
nums[i] = nums[target_index] # Bug: Modifying original array!
return nums
Why it fails:
- Later iterations would use already-modified values instead of the original values
- For example, if index 0 gets modified, and index 1 needs to reference index 0, it would get the wrong value
The Solution: Create a separate result array and keep the original array unchanged:
result = []
for i, value in enumerate(nums):
# ... transformation logic
result.append(transformed_value)
3. Off-by-One Errors in Understanding "Steps"
The Pitfall: Misunderstanding what "move X steps" means - some might think moving 1 step right from index 0 means staying at index 0 (counting the current position as step 0).
The Solution: Remember that movements are relative displacements:
- Moving 1 step right from index 0 → index 1
- Moving 2 steps right from index 0 → index 2
- The formula
(i + value + n) % n
correctly handles this as addition
4. Forgetting the Special Case for Zero
The Pitfall:
Treating zero like any other value and applying the modulo formula, which would incorrectly return nums[i]
instead of 0
.
Example of the Bug:
# INCORRECT - treats 0 like any other value target_index = (i + value + n) % n result.append(nums[target_index]) # Would append nums[i] when value is 0
The Solution: Explicitly check for zero values:
if value == 0: result.append(0) else: target_index = (i + value + n) % n result.append(nums[target_index])
What is the best way of checking if an element exists in an unsorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
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
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!