[/dsa/leetcode]

448 - Find All Numbers Disappeared in an Array

Wednesday, 16 September 2026

<easy> [problem]

Cyclic sort with a duplicate-safe swap guard, and the sign marking alternative that records presence in the sign bit.

{array}{hashing}

Problem

Given an array nums of n integers where nums[i] is in the range [1, n], return an array of all the integers in the range [1, n] that do not appear in nums.

Input: nums = [4,3,2,7,8,2,3,1]
Output: [5,6]

Input: nums = [1,1]
Output: [2]

Constraints:

  • n == nums.length
  • 1 <= n <= 10^5
  • 1 <= nums[i] <= n

Follow-up: could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.

Approach

Send each value v to index v - 1. Anything present ends up home, and the slots still holding the wrong value name exactly the numbers that never showed up. See the cyclic sort note.

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        const int n = nums.size();
        int i = 1;
        while (i <= n) {
            int corr = nums[i - 1];
            if (nums[corr - 1] != corr) {
                swap(nums[i - 1], nums[corr - 1]);
            } else {
                i++;
            }
        }

        vector<int> res;
        for (int j = 1; j <= n; j++)
            if (nums[j - 1] != j) res.push_back(j);
        return res;
    }
};
nums = [4, 3, 2, 7, 8, 2, 3, 1]
                            ->  [7, 3, 2, 4, 8, 2, 3, 1]   4 to index 3
                            ->  [3, 3, 2, 4, 8, 2, 7, 1]   7 to index 6
                            ->  [2, 3, 3, 4, 8, 2, 7, 1]   3 to index 2
                            ->  [3, 2, 3, 4, 8, 2, 7, 1]   2 to index 1
                                 ^ nums[2] already holds 3, so i advances
                            ->  [1, 2, 3, 4, 8, 2, 7, 3]   1 to index 0
                                settled: [1,2,3,4,8,2,7,3]

scan: index 4 holds 8 != 5, index 5 holds 2 != 6  ->  [5, 6]
  • time: O(n) — each swap puts one value permanently home, so at most n swaps across the whole loop, amortized O(n) even though i doesn’t advance on a swap
  • space: O(1) — in place, though the input is rearranged

Sign Marking

The values are all positive and all valid indices, so the sign bit of each slot is free storage. First pass: for every value v, flip nums[v - 1] negative to mark ”v was seen”. Second pass: any slot still positive was never marked, so its index plus one is missing.

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        const int n = nums.size();
        for (int x : nums) {
            int idx = abs(x) - 1;
            if (nums[idx] > 0) nums[idx] = -nums[idx];
        }

        vector<int> res;
        for (int i = 0; i < n; i++)
            if (nums[i] > 0) res.push_back(i + 1);
        return res;
    }
};
  • time: O(n) — two passes, no swapping
  • space: O(1)
quantinium © 2026