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
0at index0: target =[0] - Insert
1at index1: target =[0,1] - Insert
2at index2: target =[0,1,2] - Insert
3at index2: target =[0,1,3,2](the2shifts right) - Insert
4at 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
targetthat 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):xis the value to insert (fromnums)iis the position where we insert it (fromindex)- We use
target.insert(i, x)to insert valuexat positioni
-
Return the result: After processing all pairs,
targetcontains the desired array.
How insert() works:
When we call target.insert(i, x), Python:
- Places
xat positioni - Shifts all elements from position
ionwards 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
1at index0:target = [1] - Insert
2at index1:target = [1, 2] - Insert
3at 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 5-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
4at index0 - Since the array is empty,
4becomes the first element target = [4]
Step 2: Process (2, 0)
- Insert value
2at index0 - The existing element
4at index0shifts right to index1 target = [2, 4]
Step 3: Process (1, 1)
- Insert value
1at index1 - Element
4at index1shifts right to index2 target = [2, 1, 4]
Step 4: Process (3, 3)
- Insert value
3at 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
251class 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}
331class 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};
181/**
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}
21Time 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.
Which of the following uses divide and conquer strategy?
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 If you prefer videos here's a video that explains recursion in a fun and easy way 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 him
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!