title: Build Array from Permutation slug: build-array-from-permutation difficulty: easy leetcode_id: 1920 leetcode_url: https://leetcode.com/problems/build-array-from-permutation/ categories: - arrays patterns: - matrix-traversal description: | Given a **zero-based permutation** `nums` (**0-indexed**), build an array `ans` of the **same length** where `ans[i] = nums[nums[i]]` for each `0 <= i < nums.length` and return it. A **zero-based permutation** `nums` is an array of **distinct** integers from `0` to `nums.length - 1` (**inclusive**). constraints: | - `1 <= nums.length <= 1000` - `0 <= nums[i] < nums.length` - The elements in `nums` are **distinct** examples: - input: "nums = [0,2,1,5,3,4]" output: "[0,1,2,4,5,3]" explanation: "ans[i] = nums[nums[i]]. For i=0: nums[nums[0]] = nums[0] = 0. For i=1: nums[nums[1]] = nums[2] = 1. And so on." - input: "nums = [5,0,1,2,3,4]" output: "[4,5,0,1,2,3]" explanation: "For i=0: nums[nums[0]] = nums[5] = 4. For i=1: nums[nums[1]] = nums[0] = 5. And so on." explanation: intuition: | Think of this problem as following a chain of pointers. Each element in the array tells you "go look at this index," and then you report what you find there. Imagine the array as a treasure map where each location contains coordinates to another location. For each position `i`, you first look at `nums[i]` to get a new location, then you go to that location and record what you find. The result is your answer for position `i`. The key insight is that since `nums` is a permutation of `0` to `n-1`, every index is valid and every value appears exactly once. This guarantees that `nums[nums[i]]` will never go out of bounds — every value in the array is a valid index. For the follow-up challenge of O(1) space, we can encode two values in each position using the mathematical property that for any value `a` and `b` where both are less than `n`, we can store `a + n * b` and later extract `a` as `value % n` and `b` as `value // n`. approach: | We solve this using **direct simulation**: **Step 1: Create a result array** - Initialise an empty array `ans` of the same length as `nums` - We'll fill each position with the required value   **Step 2: Apply the transformation** - For each index `i` from `0` to `n-1`: - Look up `nums[i]` to get the intermediate index - Look up `nums[nums[i]]` to get the final value - Store this value in `ans[i]`   **Step 3: Return the result** - Return the completed `ans` array   For the **O(1) space** solution, we use a clever encoding trick: **Step 1: Encode both values in each position** - For each index `i`, we want to store both the original `nums[i]` and the new `nums[nums[i]]` - Use the formula: `nums[i] = nums[i] + n * (nums[nums[i]] % n)` - The `% n` is crucial because some positions may already have been encoded   **Step 2: Decode to get final values** - For each index `i`, extract the encoded value using integer division: `nums[i] = nums[i] // n` common_pitfalls: - title: Modifying Array While Reading description: | In the O(1) space approach, if you simply set `nums[i] = nums[nums[i]]`, you corrupt the array for later indices that need to read the original values. For example, with `nums = [0, 2, 1]`, if you set `nums[0] = nums[nums[0]] = nums[0] = 0`, then when computing `nums[1]`, you need `nums[nums[1]] = nums[2] = 1`, which is still correct. But consider `nums = [1, 0]`: setting `nums[0] = nums[1] = 0` means when computing `nums[1]`, you need `nums[nums[1]] = nums[0]`, but `nums[0]` is now `0` instead of `1`. wrong_approach: "Overwriting values directly in the input array" correct_approach: "Either use a separate result array or encode both values together" - title: Forgetting Modulo When Encoding description: | When using the encoding trick, the value at `nums[i]` might already be encoded (contains both old and new values). Reading `nums[nums[i]]` directly would give the wrong result. Always use `nums[nums[i] % n]` to extract the original value, since `original_value = encoded_value % n`. wrong_approach: "nums[i] += n * nums[nums[i]]" correct_approach: "nums[i] += n * (nums[nums[i]] % n)" - title: Integer Overflow Concerns description: | In some languages, `nums[i] + n * encoded_value` could overflow if `n` is large. With the constraint `n <= 1000`, the maximum encoded value is `999 + 1000 * 999 = 999,999`, which fits comfortably in a 32-bit integer. In Python, integers have arbitrary precision, so this isn't a concern, but be mindful in languages like C++ or Java. key_takeaways: - "**Index chaining**: When array values represent indices, you can follow chains with `arr[arr[i]]`" - "**Encoding two values**: The formula `a + n * b` stores two values `< n` in one integer, extractable via `% n` and `// n`" - "**Permutation properties**: A permutation of `0` to `n-1` guarantees all indices are valid and all values are distinct" - "**In-place modification**: When modifying an array in-place, ensure you can still recover original values when needed" time_complexity: "O(n). We iterate through the array once (or twice for the O(1) space solution)." space_complexity: "O(n) for the straightforward solution using a result array. O(1) for the encoding approach that modifies the input in-place." solutions: - approach_name: Direct Simulation is_optimal: true code: | def buildArray(nums: list[int]) -> list[int]: n = len(nums) # Create result array with the same length ans = [0] * n # For each index, follow the chain: i -> nums[i] -> nums[nums[i]] for i in range(n): ans[i] = nums[nums[i]] return ans explanation: | **Time Complexity:** O(n) — Single pass through the array. **Space Complexity:** O(n) — We create a new array of size n. This is the most straightforward approach: create a new array and fill each position by following the index chain. Clean, readable, and efficient. - approach_name: In-Place with Encoding is_optimal: false code: | def buildArray(nums: list[int]) -> list[int]: n = len(nums) # First pass: encode both old and new values # nums[i] = old_value + n * new_value for i in range(n): # Use % n to get original value (in case already encoded) new_value = nums[nums[i] % n] % n nums[i] = nums[i] + n * new_value # Second pass: decode to get only the new values for i in range(n): nums[i] = nums[i] // n return nums explanation: | **Time Complexity:** O(n) — Two passes through the array. **Space Complexity:** O(1) — Only modifies the input array in-place. This clever approach stores two values in each position using the encoding `old + n * new`. The first pass encodes, the second pass decodes. While it achieves O(1) space, it's harder to understand and modifies the input, which may not always be desirable.