题目:

给定一个包含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.\n", 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.\n", result);
    return 0;
}

结果:

很郁闷啊,明明改进了,结果却跟没改进时候一模一样,不知道为什么。。。


参考:一起玩算法02

推荐一位干货up主:正月点灯笼