C# Find disappeared number in an array. ~85% runtime and ~99% memory

First, the naive solution, using an extra collection, as a hashset:

    var res=new HashSet<int>(Enumerable.Range(1,nums.Length));
    foreach (var item in nums)
        res.Remove(item);
    return res.ToArray()

Explanation: You create a hashset of numbers 1-n, and then remove numbers already at the original array. Using hashset instead of list makes runtime faster, as hashsets are the fastest dynamic collection.

However, the description asked to use the least memory possible. To do so, we must use the original array only, both for processing and as result array. Code gets way uglier, tho. The trick here is iterate the array backwards, and swapping each number to its correct position, which is "nums[i+1]". Then we scan the array again, and check which number is not present (meaning it was a disappeared number).

    for (int i=nums.Length-1;i>=0;i--)  // scan backwards
        {
        while (nums[i]!=i+1 && nums[nums[i]-1]!=nums[i]) // check if number is in correct position
            (nums[i],nums[nums[i]-1])=(nums[nums[i]-1],nums[i]); // swap number with its correct position 
        } // line above uses "tuple swap" to avoid temp variable.
    int idx=0; // now we will move all wrong (missing) numbers to the beginning of the array. 
    for (int i=0;i<nums.Length;i++) // iterate array again 
        if (nums[i]!=i+1) nums[idx++]=i+1; // move to beginning of the array, increment index
    return nums[0..idx]; // return wrong numbers, using C# 8.0 index range ("split") function

Above solution will only use 1 int of extra memory, which is the variable idx. Every operation is done at the original array.

Comments (0)