有數組 A 長度 N-3,包含 1 到 N 中除 3 個缺失數字外的所有數,順序打亂。N=10000。要求快速找出 3 個缺失數。
利用數字範圍已知(1~N),建立大小 N+1 的輔助陣列 B,下標對應數字值,值為 0/1 標記是否出現。
int B[N+1] = {0};(索引 1~N 有效,0 忽略)。A,對每個 A[i] 置 B[A[i]] = 1。B[1...N],值為 0 的下標即為缺失數字。void findMissing(int A[], int n_minus_3) {
int N = n_minus_3 + 3;
int *B = (int*)calloc(N + 1, sizeof(int)); // 自動歸零
for (int i = 0; i < n_minus_3; i++) {
if (A[i] >= 1 && A[i] <= N) B[A[i]] = 1;
}
printf("缺失的數字:");
for (int i = 1; i <= N; i++) {
if (B[i] == 0) printf("%d ", i);
}
printf("\n");
free(B);
}
O(N) 兩次線性掃描。O(N) 輔助陣列(N=10000 约 40KB,極小)。| 變體 | 思路 | 複雜度 |
|---|---|---|
| 只缺 1 個數 | 求和公式 N*(N+1)/2 - sum(A) | O(N) 時間,O(1) 空間 |
| 缺 2 個數 | 建立 sum 和 sum_of_squares 方程組求解 | O(N) 時間,O(1) 空間 |
| 缺 k 個數 (k 固定小) | 位圖 或 k 次遍歷構造多項式 | O(N) 時間,O(N) 或 O(k) 空間 |
| 不可修改原數組、嚴格 O(1) 空間 | 循環排序/置換法(將數字放到對應下標) | O(N) 時間,O(1) 空間,但修改數組 |
| 數據流/超大 N | 布隆過濾器、MapReduce 分布式計數 | 視具體架構 |
若 N 極大(如 1 億),int 陣列 400MB 過大。可用位圖:每個數佔 1 bit,N=1億 僅需 ~12.5MB。
// 位圖版
unsigned char *bitmap = calloc((N >> 3) + 1, 1);
#define SET_BIT(x) (bitmap[(x)>>3] |= (1 << ((x)&7)))
#define TEST_BIT(x) (bitmap[(x)>>3] & (1 << ((x)&7)))
for (int i=0; i
「標記陣列 / 位圖」是解決**有限範圍整數集合差集**問題的通用利器:簡單、快速、易於並行化。面試中先給出 O(N) 空間解法,再根據面試官追問優化到 O(1) 空間(修改原數組)或位圖(巨大 N),展現完整工程思維。