Talentd
FleetCode
Make and follow sheets.Sign in

Recover the Original Array solution and explanation

HardArrayEnumerationHash TableSorting5 min read42.0% acceptanceUpdated 9 Apr 2026
Recover the Original Array | Leetcode 2122 | Contest 273 | Tricky Solution 🔥🔥🔥🔥Coding Decoded · 15:28 · 2K viewsWatch on YouTube
9 more videos on this problem
  1. Recover the Original Array | Leetcode 2122 | Contest 273 | Tricky Solution 🔥🔥🔥🔥Coding Decoded · 15:28 · 2K views
  2. Recover the Original Array | LeetCode Weekly Contest 273 | Hitesh TripathiCode Era · 20:01 · 604 views
  3. Leetcode:Recover the original ArrayCoding For Dummies · 14:38 · 468 views
  4. 2122. Recover the Original Array (Leetcode Hard)Programming Live with Larry · 16:51 · 448 views
  5. 【每日一题】LeetCode 2122. Recover the Original ArrayHuifeng Guan · 25:21 · 396 views
  6. Recover the Original Array (Leetcode Weekly 273)Soumya Bhattacharjee · 7:42 · 176 views
  7. Leetcode 2122. Recover the Original Array (2 pointers and greedy)LetsCode · 22:10 · 18 views
  8. Recover the Original Array LeetCode 2122algorithmswala · 3:18 · 6 views
  9. LeetCode 2122: Recover the Original ArrayAlitaCode · 30:09 · 2 views
  10. 2122 recover the original arrayCodePen · 1:10 · 2 views

The problem

Alice had a 0-indexed array arr consisting of n positive integers. She chose an arbitrary positive integer k and created two new 0-indexed integer arrays lower and higher in the following manner:

  1. lower[i] = arr[i] - k, for every index i where 0 <= i < n
  2. higher[i] = arr[i] + k, for every index i where 0 <= i < n

Unfortunately, Alice lost all three arrays. However, she remembers the integers that were present in the arrays lower and higher, but not the array each integer belonged to. Help Alice and recover the original array.

Given an array nums consisting of 2n integers, where exactly n of the integers were present in lower and the remaining in higher, return the original array arr. In case the answer is not unique, return any valid array.

Note: The test cases are generated such that there exists at least one valid array arr.

Example 1:

Input: nums = [2,10,6,4,8,12]
Output: [3,7,11]
Explanation:
If arr = [3,7,11] and k = 1, we get lower = [2,6,10] and higher = [4,8,12].
Combining lower and higher gives us [2,6,10,4,8,12], which is a permutation of nums.
Another valid possibility is that arr = [5,7,9] and k = 3. In that case, lower = [2,4,6] and higher = [8,10,12]. 

Example 2:

Input: nums = [1,1,3,3]
Output: [2,2]
Explanation:
If arr = [2,2] and k = 1, we get lower = [1,1] and higher = [3,3].
Combining lower and higher gives us [1,1,3,3], which is equal to nums.
Note that arr cannot be [1,3] because in that case, the only possible way to obtain [1,1,3,3] is with k = 0.
This is invalid since k must be positive.

Example 3:

Input: nums = [5,435]
Output: [220]
Explanation:
The only possible combination is arr = [220] and k = 215. Using them, we get lower = [5] and higher = [435].

Constraints:

  • 2 * n == nums.length
  • 1 <= n <= 1000
  • 1 <= nums[i] <= 109
  • The test cases are generated such that there exists at least one valid array arr.

Approach overview

Problem Overview: You receive an array formed by taking every value x from an unknown array and inserting both x - k and x + k. The values are shuffled. The task is to reconstruct the original array and determine the elements x.

Approach 1: Sort and Compare (Sorting + Hash Table) (Time: O(n^2), Space: O(n))

Start by sorting the array. In the transformed array, the smallest value must correspond to x - k for some original element x. Try pairing it with every larger element to guess the value of k. For a candidate pair (nums[0], nums[j]), compute k = (nums[j] - nums[0]) / 2. Only continue if the difference is positive and even. Once a candidate k is chosen, rebuild the original array by greedily matching each value a with a + 2k. A frequency map (from a hash table) tracks remaining elements so each pair is used exactly once.

During reconstruction, iterate through the sorted array. If a number is still unused, treat it as x - k. Check whether x + k (which appears as a + 2k) exists in the frequency map. If it does, decrease counts for both numbers and append a + k to the result. If any required pair is missing, the chosen k is invalid and you try the next candidate.

Sorting simplifies pairing because smaller values are processed first. The hash map ensures constant-time availability checks. The algorithm essentially enumerates valid differences while verifying them using counting. Concepts from sorting, arrays, and hash-based counting drive the solution.

Recommended for interviews: The sorting + enumeration approach is what interviewers typically expect. Brute-force pairing without ordering becomes messy and error-prone. Sorting the array first and validating each possible k shows clear reasoning, controlled enumeration, and correct use of hash maps to enforce pair constraints.

Approach 1: Sort and Compare

By sorting the array, you can effectively guess the potential value of k by comparing and calculating possible values of k from the smallest or largest differences. For each guess of k, attempt reconstructing the original array.

def recoverArray(nums):
    nums.sort()
    n = len(nums) // 2
    
    for i in range(1, len(nums)):
        if (nums[i] - nums[0]) % 2 != 0:
            continue
        k = (nums[i] - nums[0]) // 2
        if k == 0:
            continue
        arr = []
        used = [False] * len(nums)
        valid = True
        
        for j in range(len(nums)):
            if used[j]:
                continue
            target = nums[j] + 2*k
            try:
                idx = nums.index(target)
            except ValueError:
                valid = False
                break
            if used[idx]:
                continue
            arr.append(nums[j] + k)
            used[j] = used[idx] = True
        if valid:
            return arr
    
    return []

nums = [2, 10, 6, 4, 8, 12]
print(recoverArray(nums))
import java.util.*;

public class Solution {
    public int[] recoverArray(int[] nums) {
        Arrays.sort(nums);
        int n = nums.length / 2;
        
        for (int i = 1; i < nums.length; i++) {
            if ((nums[i] - nums[0]) % 2 != 0) continue;
            int k = (nums[i] - nums[0]) / 2;
            if (k == 0) continue;
            
            int[] arr = new int[n];
            boolean[] used = new boolean[nums.length];
            Arrays.fill(used, false);
            boolean valid = true;
            int j = 0;
            for (int num : nums) {
                if (used[j]) continue;
                int target = num + 2 * k;
                int idx = -1;
                for (int m = 0; m < nums.length; m++) {
                    if (!used[m] && nums[m] == target) {
                        idx = m;
                        break;
                    }
                }
                if (idx == -1) {
                    valid = false;
                    break;
                }
                arr[j++] = num + k;
                used[j] = used[idx] = true;
            }
            if (valid) return arr;
        }
        return new int[0];
    }

    public static void main(String[] args) {
        Solution sol = new Solution();
        int[] nums = {2, 10, 6, 4, 8, 12};
        int[] result = sol.recoverArray(nums);
        System.out.println(Arrays.toString(result));
    }
}
#include <vector>
#include <algorithm>
using namespace std;

vector<int> recoverArray(vector<int>& nums) {
    sort(nums.begin(), nums.end());
    int n = nums.size() / 2;
    
    for (int i = 1; i < nums.size(); i++) {
        if ((nums[i] - nums[0]) % 2 != 0) continue;
        int k = (nums[i] - nums[0]) / 2;
        if (k == 0) continue;
        
        vector<int> result;
        vector<bool> used(nums.size(), false);
        bool valid = true;
        result.reserve(n);
        
        for (int j = 0; j < nums.size(); ++j) {
            if (used[j]) continue;
            auto it = find(nums.begin(), nums.end(), nums[j] + 2 * k);
            if (it != nums.end() && !used[it - nums.begin()]) {
                used[j] = used[it - nums.begin()] = true;
                result.push_back(nums[j] + k);
            } else {
                valid = false;
                break;
            }
        }
        if (valid) return result;
    }
    return {};
}

int main() {
    vector<int> nums = {2, 10, 6, 4, 8, 12};
    auto result = recoverArray(nums);
    
    printf("[");
    for (int i = 0; i < result.size(); i++) {
        printf("%d%s", result[i], i == result.size() - 1 ? "" : ", ");
    }
    printf("]\n");
    
    return 0;
}
const recoverArray = (nums) => {
  nums.sort((a, b) => a - b);
  const n = nums.length / 2;
  
  for (let i = 1; i < nums.length; i++) {
    if ((nums[i] - nums[0]) % 2 !== 0) continue;
    const k = (nums[i] - nums[0]) / 2;
    if (k <= 0) continue;
    
    const arr = [];
    const used = Array(nums.length).fill(false);
    let valid = true;
    
    for (let j = 0; j < nums.length; j++) {
      if (used[j]) continue;
      const target = nums[j] + 2 * k;
      const index = nums.indexOf(target);
      if (index === -1 || used[index]) {
        valid = false;
        break;
      }
      arr.push(nums[j] + k);
      used[j] = used[index] = true;
    }
    if (valid) return arr;
  }

  return [];
};

const nums = [2, 10, 6, 4, 8, 12];
console.log(recoverArray(nums));
#include <stdio.h>
#include <stdlib.h>

int compare(const void *a, const void *b) {
    return (*(int *)a - *(int *)b);
}

int* recoverArray(int* nums, int numsSize, int* returnSize) {
    qsort(nums, numsSize, sizeof(int), compare);
    int n = numsSize / 2;
    
    for (int i = 1; i < numsSize; i++) {
        int k = (nums[i] - nums[0]) / 2;
        if (k <= 0) continue;
        
        int *used = calloc(numsSize, sizeof(int));
        int *arr = malloc(n * sizeof(int));
        int found = 1;
        int j = 0;
        for (int l = 0; l < numsSize; l++) {
            if (used[l]) continue;
            int target = nums[l] + 2*k;
            int position = -1;
            for (int m = 0; m < numsSize; m++) {
                if (!used[m] && nums[m] == target) {
                    position = m;
                    break;
                }
            }
            if (position == -1) {
                found = 0;
                break;
            }
            arr[j++] = nums[l] + k;
            used[l] = used[position] = 1;
        }
        free(used);
        if (found) {
            *returnSize = n;
            return arr;
        } else {
            free(arr);
        }
    }
    return NULL;
}

int main() {
    int nums[] = {2, 10, 6, 4, 8, 12};
    int returnSize;
    int* result = recoverArray(nums, 6, &returnSize);
    
    printf("[");
    for (int i = 0; i < returnSize; i++) {
        printf("%d%s", result[i], i == returnSize - 1 ? "": ", ");
    }
    printf("]\n");
    
    free(result);
    return 0;
}
using System;
using System.Collections.Generic;

public class Solution {
    public int[] RecoverArray(int[] nums) {
        Array.Sort(nums);
        int n = nums.Length / 2;
        
        for (int i = 1; i < nums.Length; i++) {
            if ((nums[i] - nums[0]) % 2 != 0) continue;
            int k = (nums[i] - nums[0]) / 2;
            if (k <= 0) continue;
            
            List<int> arr = new List<int>();
            bool[] used = new bool[nums.Length];
            bool valid = true;
            
            for (int j = 0; j < nums.Length; j++) {
                if (used[j]) continue;
                int target = nums[j] + 2 * k;
                int index = Array.IndexOf(nums, target);
                if (index == -1 || used[index]) {
                    valid = false;
                    break;
                }
                arr.Add(nums[j] + k);
                used[j] = used[index] = true;
            }
            if (valid) return arr.ToArray();
        }

        return new int[0];
    }

    public static void Main(string[] args) {
        Solution sol = new Solution();
        int[] nums = {2, 10, 6, 4, 8, 12};
        int[] result = sol.RecoverArray(nums);
        Console.WriteLine("[{0}]", string.Join(", ", result));
    }
}

Sort the input nums and derive potential k values by iterating over differences between sorted elements. Attempt to reconstruct an array for each valid k, and return once validation succeeds.

Complexity

Time Complexity: O(n^2): Requires checking each possible pair derived from sorted differences.
Space Complexity: O(n) to manage tracking of used elements and interim validation arrays.

Try this approach in the editor

Approach 2: Default Approach

func recoverArray(nums []int) []int {
	sort.Ints(nums)
	for i, n := 1, len(nums); i < n; i++ {
		d := nums[i] - nums[0]
		if d == 0 || d%2 == 1 {
			continue
		}
		vis := make([]bool, n)
		vis[i] = true
		ans := []int{(nums[0] + nums[i]) >> 1}
		for l, r := 1, i+1; r < n; l, r = l+1, r+1 {
			for l < n && vis[l] {
				l++
			}
			for r < n && nums[r]-nums[l] < d {
				r++
			}
			if r == n || nums[r]-nums[l] > d {
				break
			}
			vis[r] = true
			ans = append(ans, (nums[l]+nums[r])>>1)
		}
		if len(ans) == (n >> 1) {
			return ans
		}
	}
	return []int{}
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Sort and Compare

Time Complexity: O(n^2): Requires checking each possible pair derived from sorted differences.
Space Complexity: O(n) to manage tracking of used elements and interim validation arrays.

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Brute Force Pair TestingO(n^3)O(n)Conceptual baseline to understand how pairs form original values
Sort + Enumerate k with Hash MapO(n^2)O(n)General solution used in interviews and competitive programming
Sort + Greedy Pair MatchingO(n^2)O(n)When using frequency counting to greedily match a with a+2k

Frequently asked questions

Is Recover the Original Array easy or hard?

Recover the Original Array is rated Hard on LeetCode. The challenge comes from identifying the correct value of k and validating pairs efficiently while handling duplicates and maintaining element counts.

Recover the Original Array Python/Java solution

Most implementations follow the same logic across languages: sort the array, enumerate candidate k values, then use a hash map to match pairs a and a + 2k. Python uses collections.Counter, while Java typically uses HashMap for frequency tracking.

How to solve Recover the Original Array in O(n)?

An O(n) solution is generally not feasible because the algorithm must test multiple candidate values of k derived from pair differences. Each candidate requires verifying pairings across the array. The practical optimal solution is O(n^2) after sorting.

What is the best approach for Recover the Original Array?

The most reliable approach sorts the array and enumerates possible values of k using differences with the smallest element. For each candidate k, a hash map validates whether every value a can be paired with a + 2k. This approach runs in O(n^2) time with O(n) extra space and is the expected interview solution.

Is Recover the Original Array asked at Google/Amazon/Meta?

Problems involving array reconstruction, pair differences, and frequency matching appear in interviews at companies like Google, Amazon, and Meta. While the exact problem may vary, the underlying techniques—sorting, hash maps, and greedy pairing—are common interview patterns.

What data structure is used in Recover the Original Array?

A hash table (frequency map) is the main data structure. It tracks how many times each value appears so elements can be paired correctly as a and a + 2k. Sorting the array beforehand helps process elements in deterministic order.

What is the time complexity of Recover the Original Array?

The common sorting and enumeration solution runs in O(n^2) time. Sorting the array takes O(n log n), and testing each candidate k requires scanning the array with hash map checks, which leads to O(n^2) overall. Space complexity is O(n) for frequency tracking.

Comments

Now write it yourselfClose this page and solve Recover the Original Array in the editor, without looking.
Practise Recover the Original Array