1389. Create Target Array in the Given Order
Problem Description
You are given two arrays: nums
and index
, both containing integers. Your task is to build a target array by following these steps:
- Start with an empty target array
- Read elements from both arrays simultaneously from left to right (reading
nums[i]
andindex[i]
together) - For each pair, insert the value
nums[i]
at positionindex[i]
in the target array - Continue until all elements have been processed
The key point is that when you insert a value at a specific index, any existing elements at or after that position shift to the right to make room for the new element.
For example, if nums = [0,1,2,3,4]
and index = [0,1,2,2,1]
:
- Insert
0
at index0
: target =[0]
- Insert
1
at index1
: target =[0,1]
- Insert
2
at index2
: target =[0,1,2]
- Insert
3
at index2
: target =[0,1,3,2]
(the2
shifts right) - Insert
4
at index1
: target =[0,4,1,3,2]
(elements from index 1 onward shift right)
The solution uses Python's insert()
method which handles the shifting automatically. The zip()
function pairs up corresponding elements from nums
and index
arrays, and for each pair (x, i)
, it inserts value x
at position i
in the target array.
Intuition
The problem asks us to build an array by inserting elements at specific positions. The natural approach is to simulate exactly what the problem describes - start with an empty array and perform each insertion operation in order.
Since we need to process two arrays (nums
and index
) together where nums[i]
tells us what value to insert and index[i]
tells us where to insert it, we can pair these elements together. This naturally leads to using zip()
to iterate through both arrays simultaneously.
The core insight is that we don't need any complex data structure or algorithm here. Python's list already provides an insert()
method that does exactly what we need - it inserts an element at a given position and automatically shifts all subsequent elements to the right. This handles all the complexity of maintaining the correct order when inserting into the middle of the array.
Why does this straightforward simulation work? The problem guarantees that all insertion operations are valid, meaning we'll never try to insert at an invalid index. This allows us to directly use target.insert(i, x)
without any bounds checking or special cases.
The time complexity might seem concerning since each insert()
operation can take O(n) time in the worst case (when inserting at the beginning), but given the problem constraints and the guarantee of valid operations, this direct simulation is the most intuitive and clean solution.
Solution Approach
The solution uses a straightforward simulation approach to build the target array step by step.
Implementation Steps:
-
Initialize an empty list: We create an empty list called
target
that will store our result. -
Iterate through paired elements: Using
zip(nums, index)
, we pair up corresponding elements from both arrays. This gives us tuples like(nums[0], index[0])
,(nums[1], index[1])
, and so on. -
Insert elements at specified positions: For each pair
(x, i)
:x
is the value to insert (fromnums
)i
is the position where we insert it (fromindex
)- We use
target.insert(i, x)
to insert valuex
at positioni
-
Return the result: After processing all pairs,
target
contains the desired array.
How insert()
works:
When we call target.insert(i, x)
, Python:
- Places
x
at positioni
- Shifts all elements from position
i
onwards to the right by one position - This maintains the relative order of previously inserted elements
Example walkthrough with nums = [1,2,3]
, index = [0,1,0]
:
- Start:
target = []
- Insert
1
at index0
:target = [1]
- Insert
2
at index1
:target = [1, 2]
- Insert
3
at index0
:target = [3, 1, 2]
(existing elements shift right)
The beauty of this approach is its simplicity - we let Python's built-in insert()
method handle all the complexity of array manipulation, making the code clean and easy to understand.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's trace through a small example with nums = [4, 2, 1, 3]
and index = [0, 0, 1, 3]
.
Initial state: target = []
Step 1: Process (4, 0)
- Insert value
4
at index0
- Since the array is empty,
4
becomes the first element target = [4]
Step 2: Process (2, 0)
- Insert value
2
at index0
- The existing element
4
at index0
shifts right to index1
target = [2, 4]
Step 3: Process (1, 1)
- Insert value
1
at index1
- Element
4
at index1
shifts right to index2
target = [2, 1, 4]
Step 4: Process (3, 3)
- Insert value
3
at index3
- No shifting needed as we're appending at the end
target = [2, 1, 4, 3]
The key observation is how insert()
automatically handles the shifting. When we insert 2
at index 0
in Step 2, we don't manually move 4
- the insert()
method takes care of this. Similarly, in Step 3, inserting at index 1
pushes everything from that position rightward.
This demonstrates why the simple approach of using target.insert(i, x)
for each (x, i)
pair from zip(nums, index)
correctly builds our target array.
Solution Implementation
1class Solution:
2 def createTargetArray(self, nums: List[int], index: List[int]) -> List[int]:
3 """
4 Creates a target array by inserting elements from nums at positions specified by index.
5
6 Args:
7 nums: List of integers to be inserted
8 index: List of positions where corresponding nums elements should be inserted
9
10 Returns:
11 List[int]: The resulting target array after all insertions
12 """
13 # Initialize an empty list to store the target array
14 target = []
15
16 # Iterate through nums and index arrays simultaneously
17 # For each pair (num_value, insert_position), insert num_value at insert_position
18 for num_value, insert_position in zip(nums, index):
19 # Insert the current number at the specified index position
20 # If elements exist at or after this position, they shift to the right
21 target.insert(insert_position, num_value)
22
23 # Return the constructed target array
24 return target
25
1class Solution {
2 /**
3 * Creates a target array by inserting elements from nums array at positions specified by index array.
4 * When inserting at a position, existing elements shift to the right.
5 *
6 * @param nums Array containing values to be inserted
7 * @param index Array containing positions where corresponding nums values should be inserted
8 * @return The resulting target array after all insertions
9 */
10 public int[] createTargetArray(int[] nums, int[] index) {
11 // Get the length of input arrays
12 int length = nums.length;
13
14 // Use ArrayList to handle dynamic insertions efficiently
15 List<Integer> targetList = new ArrayList<>();
16
17 // Process each element and its corresponding insertion index
18 for (int i = 0; i < length; i++) {
19 // Insert nums[i] at position index[i]
20 // ArrayList.add(index, element) shifts existing elements to the right
21 targetList.add(index[i], nums[i]);
22 }
23
24 // Convert the ArrayList back to a primitive int array
25 int[] resultArray = new int[length];
26 for (int i = 0; i < length; i++) {
27 resultArray[i] = targetList.get(i);
28 }
29
30 return resultArray;
31 }
32}
33
1class Solution {
2public:
3 vector<int> createTargetArray(vector<int>& nums, vector<int>& index) {
4 // Initialize the target array to store the result
5 vector<int> target;
6
7 // Iterate through each element in nums and index arrays
8 for (int i = 0; i < nums.size(); ++i) {
9 // Insert nums[i] at position index[i] in the target array
10 // Elements at and after index[i] will be shifted to the right
11 target.insert(target.begin() + index[i], nums[i]);
12 }
13
14 // Return the constructed target array
15 return target;
16 }
17};
18
1/**
2 * Creates a target array by inserting elements from nums array at positions specified by index array
3 * @param nums - Array of numbers to be inserted
4 * @param index - Array of indices indicating where each corresponding number should be inserted
5 * @returns The resulting target array after all insertions
6 */
7function createTargetArray(nums: number[], index: number[]): number[] {
8 // Initialize an empty result array to build the target array
9 const result: number[] = [];
10
11 // Iterate through each element in the input arrays
12 for (let i = 0; i < nums.length; i++) {
13 // Insert the current number at the specified index position
14 // splice(position, deleteCount, item) inserts item at position without deleting any elements
15 result.splice(index[i], 0, nums[i]);
16 }
17
18 // Return the constructed target array
19 return result;
20}
21
Time and Space Complexity
Time Complexity: O(n²)
The code iterates through n
elements using zip(nums, index)
, which takes O(n)
time. For each element, it performs an insert()
operation at position i
in the target
list. The insert()
operation in Python lists has a time complexity of O(k)
where k
is the number of elements that need to be shifted to the right after the insertion point. In the worst case, when we always insert at the beginning (index 0), we need to shift all existing elements, leading to:
- 1st insertion: 0 shifts
- 2nd insertion: up to 1 shift
- 3rd insertion: up to 2 shifts
- ...
- nth insertion: up to n-1 shifts
This gives us a total of 0 + 1 + 2 + ... + (n-1) = n(n-1)/2 = O(n²)
operations.
Space Complexity: O(n)
The code creates a target
list that will eventually contain all n
elements from the input. No additional data structures are used that scale with the input size. The space used by the target
list is O(n)
, which dominates the space complexity.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Misunderstanding Insert Behavior with Out-of-Bounds Indices
A common misconception is assuming that insert()
will fail or behave unexpectedly when the index is greater than the current list length. In reality, Python's insert()
method handles this gracefully by appending to the end of the list.
Example of the pitfall:
target = [1, 2, 3] target.insert(10, 99) # Index 10 is beyond list length # Result: [1, 2, 3, 99] - Simply appends to the end
Why this matters: While the problem guarantees valid indices, understanding this behavior helps avoid confusion during debugging or when modifying the solution.
2. Performance Degradation with Large Arrays
The insert()
operation has O(n) time complexity because it needs to shift elements. With n insertions, the overall time complexity becomes O(n²), which can be problematic for large inputs.
Alternative approach for better performance:
def createTargetArray(self, nums: List[int], index: List[int]) -> List[int]:
# For very large arrays, consider collecting operations first
# then building the result more efficiently
operations = list(zip(index, nums))
# If performance is critical, could use a different data structure
# like a linked list or deque for O(1) insertions
from collections import deque
target = deque()
for pos, val in operations:
# Convert to list for indexing, insert, then back to deque
temp = list(target)
temp.insert(pos, val)
target = deque(temp)
return list(target)
3. Assuming Index Values are Sorted
Developers might incorrectly assume that the index
array values are in ascending order, leading to mental model errors when tracing through the algorithm.
Incorrect assumption example:
nums = [1, 2, 3] index = [0, 1, 2] # Might assume this is always the pattern
Reality - indices can be any valid position:
nums = [1, 2, 3] index = [0, 0, 0] # All insertions at position 0 # Result: [3, 2, 1] - Elements inserted in reverse order
4. Not Accounting for Index Shifting During Insertion
When manually tracing through the algorithm, it's easy to forget that each insertion affects the indices of subsequent elements.
Visualization of the mistake:
nums = [1, 2, 3] index = [0, 1, 1] # Incorrect mental model: # "Insert 1 at position 0, 2 at position 1, 3 at position 1" # Might think: [1, 3, 2] # Correct execution: # Step 1: Insert 1 at 0 → [1] # Step 2: Insert 2 at 1 → [1, 2] # Step 3: Insert 3 at 1 → [1, 3, 2] (2 shifts right)
Solution: Always remember that insert()
shifts existing elements at or after the insertion point to the right, changing their indices for future reference.
What are the most two important steps in writing a depth first search function? (Select 2)
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!