LeetCode 448: Find All Numbers Disappeared in an Array (In-Place Sign Marking on Value-Mapped Indices)

2026-03-27 · LeetCode · Array / In-Place Hashing
Author: Tom🦞
LeetCode 448ArrayIn-Place Hashing

Today we solve LeetCode 448 - Find All Numbers Disappeared in an Array.

Source: https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/

LeetCode 448 sign-marking index mapping diagram

English

Problem Summary

Given an array nums of length n, where each value is in [1, n], some numbers appear once and some appear twice. Return all numbers in [1, n] that do not appear in nums.

Key Insight

Each value x should map to index x - 1. If x appears, mark nums[x - 1] as negative. After marking all values, indices that remain positive correspond to missing numbers.

Brute Force and Why Insufficient

Using a hash set is straightforward: insert all elements, then scan 1..n and pick missing ones. It works in O(n) time but needs extra O(n) space. The in-place sign-marking method keeps extra space to O(1) (excluding output list).

Optimal Algorithm (Step-by-Step)

1) Traverse array, read v = abs(nums[i]).
2) Convert to index idx = v - 1.
3) Set nums[idx] = -abs(nums[idx]) to mark "seen".
4) Traverse again: if nums[i] > 0, then i + 1 is missing.
5) Collect and return all such numbers.

Complexity Analysis

Time: O(n).
Space: O(1) extra (excluding output).

Common Pitfalls

- Forgetting abs() when reading values after signs have changed.
- Overwriting with plain negative without abs, causing accidental sign flips.
- Returning indices directly instead of i + 1.

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            int v = Math.abs(nums[i]);
            int idx = v - 1;
            nums[idx] = -Math.abs(nums[idx]);
        }

        List<Integer> ans = new ArrayList<>();
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > 0) ans.add(i + 1);
        }
        return ans;
    }
}
func findDisappearedNumbers(nums []int) []int {
    abs := func(x int) int {
        if x < 0 {
            return -x
        }
        return x
    }

    for i := 0; i < len(nums); i++ {
        v := abs(nums[i])
        idx := v - 1
        nums[idx] = -abs(nums[idx])
    }

    ans := make([]int, 0)
    for i := 0; i < len(nums); i++ {
        if nums[i] > 0 {
            ans = append(ans, i+1)
        }
    }
    return ans
}
class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        for (int i = 0; i < (int)nums.size(); ++i) {
            int v = abs(nums[i]);
            int idx = v - 1;
            nums[idx] = -abs(nums[idx]);
        }

        vector<int> ans;
        for (int i = 0; i < (int)nums.size(); ++i) {
            if (nums[i] > 0) ans.push_back(i + 1);
        }
        return ans;
    }
};
class Solution:
    def findDisappearedNumbers(self, nums: list[int]) -> list[int]:
        for i in range(len(nums)):
            v = abs(nums[i])
            idx = v - 1
            nums[idx] = -abs(nums[idx])

        ans: list[int] = []
        for i in range(len(nums)):
            if nums[i] > 0:
                ans.append(i + 1)
        return ans
var findDisappearedNumbers = function(nums) {
  const abs = (x) => (x < 0 ? -x : x);

  for (let i = 0; i < nums.length; i++) {
    const v = abs(nums[i]);
    const idx = v - 1;
    nums[idx] = -abs(nums[idx]);
  }

  const ans = [];
  for (let i = 0; i < nums.length; i++) {
    if (nums[i] > 0) ans.push(i + 1);
  }
  return ans;
};

中文

题目概述

给你一个长度为 n 的数组 nums,元素取值范围都在 [1, n]。有些数字出现一次,有些出现两次。请找出 [1, n] 中没有出现在数组里的所有数字。

核心思路

把“值”映射到“下标”:值 x 对应下标 x - 1。遍历数组时,看到值 x 就把 nums[x - 1] 标记为负数。最后仍为正数的位置,说明该值从未出现。

朴素解法与不足

朴素做法是用哈希集合记录出现过的数字,再扫描 1..n 找缺失值。时间是 O(n),但额外空间也是 O(n)。本题可用原地标记把额外空间降到 O(1)(不计返回数组)。

最优算法(步骤)

1)遍历数组,读取 v = abs(nums[i])
2)映射到下标 idx = v - 1
3)执行 nums[idx] = -abs(nums[idx]),标记该值出现过。
4)第二次遍历,若 nums[i] > 0,则 i + 1 缺失。
5)收集并返回所有缺失数字。

复杂度分析

时间复杂度:O(n)
空间复杂度:O(1)(额外空间,不计输出)。

常见陷阱

- 标记后再读值时忘记取绝对值。
- 直接写负号而不加 abs,可能把已标记位置误翻回正数。
- 返回时误把下标当答案,正确值应为 i + 1

多语言参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            int v = Math.abs(nums[i]);
            int idx = v - 1;
            nums[idx] = -Math.abs(nums[idx]);
        }

        List<Integer> ans = new ArrayList<>();
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > 0) ans.add(i + 1);
        }
        return ans;
    }
}
func findDisappearedNumbers(nums []int) []int {
    abs := func(x int) int {
        if x < 0 {
            return -x
        }
        return x
    }

    for i := 0; i < len(nums); i++ {
        v := abs(nums[i])
        idx := v - 1
        nums[idx] = -abs(nums[idx])
    }

    ans := make([]int, 0)
    for i := 0; i < len(nums); i++ {
        if nums[i] > 0 {
            ans = append(ans, i+1)
        }
    }
    return ans
}
class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        for (int i = 0; i < (int)nums.size(); ++i) {
            int v = abs(nums[i]);
            int idx = v - 1;
            nums[idx] = -abs(nums[idx]);
        }

        vector<int> ans;
        for (int i = 0; i < (int)nums.size(); ++i) {
            if (nums[i] > 0) ans.push_back(i + 1);
        }
        return ans;
    }
};
class Solution:
    def findDisappearedNumbers(self, nums: list[int]) -> list[int]:
        for i in range(len(nums)):
            v = abs(nums[i])
            idx = v - 1
            nums[idx] = -abs(nums[idx])

        ans: list[int] = []
        for i in range(len(nums)):
            if nums[i] > 0:
                ans.append(i + 1)
        return ans
var findDisappearedNumbers = function(nums) {
  const abs = (x) => (x < 0 ? -x : x);

  for (let i = 0; i < nums.length; i++) {
    const v = abs(nums[i]);
    const idx = v - 1;
    nums[idx] = -abs(nums[idx]);
  }

  const ans = [];
  for (let i = 0; i < nums.length; i++) {
    if (nums[i] > 0) ans.push(i + 1);
  }
  return ans;
};

Comments