LeetCode 268 給定一個包含 0, 1, 2, ..., n 中 n 個互不相同數字的陣列,找出缺失的那一個。要求 O(n) 時間、O(1) 額外空間。
完整數列和 expected = n(n+1)/2,實際陣列和 actual,差值即為缺失數字。
int missingNumber(vector<int>& nums) {
long long expected = 0, actual = 0;
int n = nums.size();
for (int i = 1; i <= n; ++i) expected += i; // 0~n 共 n+1 個數,但陣列長度為 n
for (int v : nums) actual += v;
return expected - actual;
}
注意:n 可達 10⁴~10⁵,int 足夠,但用 long long 更保險。
a ^ a = 0, a ^ 0 = a。將 0~n 與陣列所有元素異或,成對抵消,剩下的就是缺失值。
int missingNumber(vector<int>& nums) {
int res = nums.size(); // 初始化為 n,因為索引只到 n-1
for (int i = 0; i < nums.size(); ++i)
res ^= i ^ nums[i];
return res;
}
利用陣列下標與值的對應關係,將每個數字放到「應該在的位置」,最後掃描第一個 nums[i] != i 的位置。會修改輸入陣列,若不可修改則不適用。
int missingNumber(vector<int>& nums) {
int n = nums.size();
for (int i = 0; i < n; ) {
if (nums[i] < n && nums[i] != nums[nums[i]])
swap(nums[i], nums[nums[i]]);
else
++i;
}
for (int i = 0; i < n; ++i)
if (nums[i] != i) return i;
return n;
}
| 方法 | 時間 | 空間 | 修改輸入 | 優缺點 |
|---|---|---|---|---|
| 求和法 | O(n) | O(1) | 否 | 最簡單,理論上有溢位風險(實際題目範圍安全) |
| 異或法 | O(n) | O(1) | 否 | 無溢位,碼短,推薦面試首選 |
| 原地置換 | O(n) | O(1) | 是 | 通用性強,可延伸至「找出所有缺失/重複數字」 |
[0,1,3] → 2 [0] → 1 [1] → 0 [0,1,2,3,4] → 5 [] → 0 (n=0 時陣列為空,缺失 0)