Nameless Site

But one day, you will stand before its decrepit gate,without really knowing why.

0%

缺失的数字

来自Leetcode第268题缺失数字

给定一个包含 0, 1, 2, ..., nn 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。

示例 1:

1
2
输入: [3,0,1]
输出: 2

Map

利用数组标记各个数字是否出现,最后遍历数组,找到没出现的数字。

1
2
3
4
5
6
7
8
9
10
11
public int missingNumber(int[] nums) {
if(nums.length == 0)
return 0;
int[] map = new int[nums.length + 1];
for(int n : nums)
map[n] = 1;
for(int i = 0 ; i < map.length; i++)
if(map[i] == 0)
return i;
return nums.length + 1;
}

异或位运算

来自官方题解

我们知道数组中有 n 个数,并且缺失的数在 [0..n][0..n] 中。因此我们可以先得到 [0..n][0..n] 的异或值,再将结果对数组中的每一个数进行一次异或运算。未缺失的数在 [0..n][0..n] 和数组中各出现一次,因此异或后得到 0。而缺失的数字只在 [0..n][0..n] 中出现了一次,在数组中没有出现,因此最终的异或结果即为这个缺失的数字。

1
2
3
4
5
6
7
8
public int missingNumber(int[] nums) {
int missing = nums.length;
for (int i = 0; i < nums.length; i++) {
missing ^= i ^ nums[i];
}
return missing;
}
}

求和公式

我们可以用 高斯求和公式 求出 [0..n][0..n] 的和,减去数组中所有数的和,就得到了缺失的数字。

1
2
3
4
5
6
7
public int missingNumber(int[] nums) {
int expectedSum = nums.length*(nums.length + 1)/2;
int actualSum = 0;
for (int num : nums) actualSum += num;
return expectedSum - actualSum;
}
}

也可以遍历一遍数组,在把0-n这n个自然数全加起来的同时也减去nums[i]

1
2
3
4
5
6
7
8
public int missingNumber(int[] nums) {
int sum = 0;
for (int i = 1; i <= nums.length; i++) {
sum += i;
sum -= nums[i - 1];
}
return sum;
}