3379. Transformed Array
Problem Description
You are given an integer array nums
that represents a circular array. Your task is to create a new array result
of the same size, following these rules:
For each index i
(where 0 <= i < nums.length
), perform the following independent actions:
- If
nums[i] > 0
: Start at indexi
and movenums[i]
steps to the right in the circular array. Setresult[i]
to the value of the index where you land. - If
nums[i] < 0
: Start at indexi
and moveabs(nums[i])
steps to the left in the circular array. Setresult[i]
to the value of the index where you land. - If
nums[i] == 0
: Setresult[i]
tonums[i]
.
Return the new array result
.
Note: Since nums
is circular, moving past the last element wraps around to the beginning, and moving before the first element wraps back to the end.
Intuition
To solve this problem, the primary challenge is dealing with the circular nature of the array. The problem requires moving either to the right or left based on the value at each position:
-
Movement Direction: Determine the direction based on the sign of the integer at each index:
- A positive number indicates movement to the right.
- A negative number indicates movement to the left.
- Zero results in no movement, and thus, the result at that position remains zero.
-
Circular Wrapping: To handle the circular aspect, when you move beyond the array bounds, you wrap around to the other end. This can be efficiently managed using the modulus operator, which provides the remainder of a division. This remainder can be adjusted to fit within the bounds of the array indices, hence facilitating circular movement.
-
Implementation Strategy:
- For each element in the array, determine the number of steps and the direction. Compute the destination index by adding the number of steps to your current index.
- Adjust the calculated index using
(current_index + steps + n) % n
, wheren
is the length of the array, ensuring the index wraps around correctly within array bounds. - Use this index to fetch the new value from
nums
and set it in theresult
array.
This approach ensures each element is processed individually and efficiently while managing the circular nature of the array using mathematical computation with modulus operations.
Solution Approach
The solution approach involves a straightforward implementation that utilizes a single pass through the nums
array with the help of mathematical operations. Here's how it works:
-
Initialize Variables:
- Create an empty list
ans
that will store the results. - Determine the length of the array
n
usinglen(nums)
.
- Create an empty list
-
Iterate Through the Array:
- Use a
for
loop withenumerate(nums)
to access both the indexi
and the elementx
at that index. - For each element, determine the action based on its value:
- Positive Value (
nums[i] > 0
):- Compute the destination index using
(i + nums[i] + n) % n
. This ensures that moving to the right, even beyond the array's end, wraps around using the modulus operator. - Append the value at this new index to
ans
.
- Compute the destination index using
- Negative Value (
nums[i] < 0
):- Compute the destination index using
(i + nums[i] + n) % n
. Here, the movement is to the left, and the modulus operator ensures no negative indices occur. - Append the value at this calculated index to
ans
.
- Compute the destination index using
- Zero Value (
nums[i] == 0
):- Directly append
0
toans
since no movement is required.
- Directly append
- Positive Value (
- Use a
-
Return the Result:
- Once the loop completes, the list
ans
contains the transformed array as required by the problem. Returnans
as the output.
- Once the loop completes, the list
The overall complexity of this solution is O(n)
due to the single pass through the array with constant-time operations, making it efficient for large datasets.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Consider the integer array nums = [2, -1, 3, 0]
. We need to construct a new array result
following the circular movement rules for each element in nums
. Let's work through each index step-by-step:
-
Index 0 (
nums[0] = 2
):- Since
nums[0]
is positive, we move2
steps to the right. - Calculate the new index:
(0 + 2 + 4) % 4 = 2
. nums[2]
is3
, so setresult[0]
to3
.
- Since
-
Index 1 (
nums[1] = -1
):- Since
nums[1]
is negative, move1
step to the left. - Calculate the new index:
(1 - 1 + 4) % 4 = 0
. nums[0]
is2
, so setresult[1]
to2
.
- Since
-
Index 2 (
nums[2] = 3
):- Since
nums[2]
is positive, we move3
steps to the right. - Calculate the new index:
(2 + 3 + 4) % 4 = 1
. nums[1]
is-1
, so setresult[2]
to-1
.
- Since
-
Index 3 (
nums[3] = 0
):- Since
nums[3]
is zero, no movement is needed. - Directly set
result[3]
to0
.
- Since
After processing each index, the result
array becomes [3, 2, -1, 0]
.
This example illustrates how the solution approach effectively handles each element in a circular manner, calculating the correct index using modulus arithmetic and populating the result
array accordingly.
Solution Implementation
1from typing import List
2
3class Solution:
4 def constructTransformedArray(self, nums: List[int]) -> List[int]:
5 # Initialize an empty list to hold the transformed values
6 transformed_array = []
7
8 # Get the length of the input list 'nums'
9 n = len(nums)
10
11 # Iterate through the list 'nums' with both index 'i' and element 'x'
12 for i, x in enumerate(nums):
13 # Calculate the new index for each element and append the result
14 # If x is zero, append 0 to the transformed list
15 transformed_array.append(nums[(i + x + n) % n] if x != 0 else 0)
16
17 # Return the constructed transformed array
18 return transformed_array
19
1class Solution {
2 public int[] constructTransformedArray(int[] nums) {
3 int n = nums.length;
4 // Initialize an array to hold the transformed results
5 int[] transformedArray = new int[n];
6
7 // Iterate over each element in the input array
8 for (int i = 0; i < n; ++i) {
9 // If the current element is not zero, calculate the new index
10 // and assign the value from the original array to the result array
11 // Computation: (i + nums[i] % n + n) % n ensures a valid index in bounds
12 transformedArray[i] = nums[i] != 0 ? nums[(i + nums[i] % n + n) % n] : 0;
13 }
14
15 // Return the transformed array
16 return transformedArray;
17 }
18}
19
1#include <vector>
2using namespace std;
3
4class Solution {
5public:
6 vector<int> constructTransformedArray(vector<int>& nums) {
7 int n = nums.size(); // Get the size of the input vector
8 vector<int> ans(n); // Initialize the result vector with the same size as nums
9
10 for (int i = 0; i < n; ++i) {
11 if (nums[i] != 0) {
12 // Compute the new index by adding the modulus of the value with n, ensuring it's positive
13 int newIndex = (i + nums[i] % n + n) % n;
14 ans[i] = nums[newIndex]; // Assign the value from the computed index
15 } else {
16 ans[i] = 0; // Assign 0 if the current element is 0
17 }
18 }
19 return ans; // Return the transformed vector
20 }
21};
22
1// The function `constructTransformedArray` transforms an array `nums` based on a specific rule.
2function constructTransformedArray(nums: number[]): number[] {
3 // Get the length of the input array `nums`.
4 const n = nums.length;
5
6 // Initialize an empty array to store the transformed values.
7 const ans: number[] = [];
8
9 // Iterate through each element in the input array `nums`.
10 for (let i = 0; i < n; ++i) {
11 // If `nums[i]` is not zero, compute the new index using modulo and offset logic, otherwise push 0.
12 // The new index is calculated as the current index plus `nums[i]` modulo `n`,
13 // adjusted with `+ n` to ensure a positive result and again modulo `n` to wrap around.
14 ans.push(nums[i] ? nums[(i + (nums[i] % n) + n) % n] : 0);
15 }
16
17 // Return the transformed array.
18 return ans;
19}
20
Time and Space Complexity
The time complexity of the given code is O(n)
where n
is the length of the input list nums
. This is because the algorithm iterates over the list nums
exactly once, performing a constant amount of work for each element.
The space complexity is also O(n)
. This is due to the creation of the list ans
which contains the transformed elements of the list nums
, and ans
will have the same length as nums
.
Learn more about how to find time and space complexity quickly.
What's the output of running the following function using input [30, 20, 10, 100, 33, 12]
?
1def fun(arr: List[int]) -> List[int]:
2 import heapq
3 heapq.heapify(arr)
4 res = []
5 for i in range(3):
6 res.append(heapq.heappop(arr))
7 return res
8
1public static int[] fun(int[] arr) {
2 int[] res = new int[3];
3 PriorityQueue<Integer> heap = new PriorityQueue<>();
4 for (int i = 0; i < arr.length; i++) {
5 heap.add(arr[i]);
6 }
7 for (int i = 0; i < 3; i++) {
8 res[i] = heap.poll();
9 }
10 return res;
11}
12
1class HeapItem {
2 constructor(item, priority = item) {
3 this.item = item;
4 this.priority = priority;
5 }
6}
7
8class MinHeap {
9 constructor() {
10 this.heap = [];
11 }
12
13 push(node) {
14 // insert the new node at the end of the heap array
15 this.heap.push(node);
16 // find the correct position for the new node
17 this.bubble_up();
18 }
19
20 bubble_up() {
21 let index = this.heap.length - 1;
22
23 while (index > 0) {
24 const element = this.heap[index];
25 const parentIndex = Math.floor((index - 1) / 2);
26 const parent = this.heap[parentIndex];
27
28 if (parent.priority <= element.priority) break;
29 // if the parent is bigger than the child then swap the parent and child
30 this.heap[index] = parent;
31 this.heap[parentIndex] = element;
32 index = parentIndex;
33 }
34 }
35
36 pop() {
37 const min = this.heap[0];
38 this.heap[0] = this.heap[this.size() - 1];
39 this.heap.pop();
40 this.bubble_down();
41 return min;
42 }
43
44 bubble_down() {
45 let index = 0;
46 let min = index;
47 const n = this.heap.length;
48
49 while (index < n) {
50 const left = 2 * index + 1;
51 const right = left + 1;
52
53 if (left < n && this.heap[left].priority < this.heap[min].priority) {
54 min = left;
55 }
56 if (right < n && this.heap[right].priority < this.heap[min].priority) {
57 min = right;
58 }
59 if (min === index) break;
60 [this.heap[min], this.heap[index]] = [this.heap[index], this.heap[min]];
61 index = min;
62 }
63 }
64
65 peek() {
66 return this.heap[0];
67 }
68
69 size() {
70 return this.heap.length;
71 }
72}
73
74function fun(arr) {
75 const heap = new MinHeap();
76 for (const x of arr) {
77 heap.push(new HeapItem(x));
78 }
79 const res = [];
80 for (let i = 0; i < 3; i++) {
81 res.push(heap.pop().item);
82 }
83 return res;
84}
85
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 algomonster s3 us east 2 amazonaws com recursion jpg You first
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!