题目:
给定一个包含n个数字的数组0, 1, 2, ... n,找出数组中缺少的数字。
例1:
输入: [3,0,1] 输出: 2
例2:
输入: [9,6,4,2,3,5,7,0,1] 输出: 8
思路:
设置一个从0到n的完整对应布尔数组,先将其全部置为false。
遍历给定数组,每读取一个数字,将布尔数组对应位置置为true。
最后遍历布尔数组,为false的即是所求。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int missingNumber(int* nums, int numsSize) {
bool* arr = malloc(sizeof(int) * (numsSize+1));
for (int i=0; i<numsSize+1; i++) {
arr[i] = false;
}
for (int i=0; i<numsSize; i++) {
int id = nums[i];
arr[id] = true;
}
for (int i=0; i<numsSize+1; i++) {
if (arr[i] == false)
return i;
}
return 0;
}
int main() {
int arr[4] = {2, 1, 3, 4};
int result = missingNumber(arr, 4);
printf("The Missing Number is %d.
", result);
return 0;
}
结果:
可以看到,虽然系统接收了这个答案,但是排名很靠后。
因为这个算法效率其实比较低,一共遍历了三次数组,时间复杂度在O(n);
此外还构造了大小为numsSize+1的数组,当数组比较大时,很占用空间。
改进思路:
因为给定的数组是0, 1, 2, ... n中剔除掉某个数字的,那么我们可以先求出0~n的和,然后依次减去数组中的元素,最后的结果即是所求。求和也不用从0加到n,可以直接用求和公式。这样只需要遍历一次数组,而且空间复杂度也降到了O(1)。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int missingNumber(int* nums, int numsSize) {
int sum = numsSize * (numsSize+1) / 2;
for (int i=0; i<numsSize; i++) {
sum = sum - nums[i];
}
return sum;
}
int main() {
int arr[4] = {0, 1, 3, 2};
int result = missingNumber(arr, 4);
printf("The Missing Number is %d.
", result);
return 0;
}
结果:
很郁闷啊,明明改进了,结果却跟没改进时候一模一样,不知道为什么。。。
参考:一起玩算法02
推荐一位干货up主:正月点灯笼