Facebook Pixel

3379. Transformed Array

EasyArraySimulation
Leetcode Link

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 index i, move nums[i] steps to the right in the circular array. The value at the landing position becomes result[i].

  • If nums[i] < 0: Starting from index i, move abs(nums[i]) steps to the left in the circular array. The value at the landing position becomes result[i].

  • If nums[i] == 0: Simply set result[i] to 0 (which is nums[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.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

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 by x steps means going to index i + x
  • Moving left from index i by x steps means going to index i - 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 when i + x ≥ 0, which correctly wraps around
  • For negative x: Adding n 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:

  1. Initialize the result array: Create an empty list ans to store the transformed values.

  2. Get array length: Store n = len(nums) for use in the modulo calculations.

  3. Iterate through each element: Use enumerate(nums) to get both the index i and value x at each position.

  4. 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
  5. 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] when x is non-zero (handles both positive and negative movements)
  • 0 when x 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 Evaluator

Example 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 using enumerate(nums), which takes O(n) time where n 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
  • 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 exactly n elements
  • The variable n stores the length of the array: O(1)
  • The loop variables i and x 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 with value = -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])
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

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

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More