1、题目描述:
LeetCode链接:消失的数字
2、解题方法:
对于此道题,我们有哪些解题思路呢?先不管其事件复杂度是否符合题目的要求,我们先分析思路。
解法1:
先将数组中的数由小到大排序,再遍历排序后的结果,如果遍历下标和该下标对应的元素不相等,则返回该下标,如果遍历结束仍然没有符合条件,说明是最后一个数字 n 缺失了,则返回数组长度 numsSize
如果用 qsort 快速排序,时间复杂度是O(N*logN),再加之还要遍历,早已大于了O(N),不符合要求。
下面代码仅作为此解法思路的展示:
int missingNumber(int* nums, int numsSize)
{
//因为缺失了一个,数组nums中只有n个元素,数组元素个数numsSize = n
//1. 将数组中的数由小到大排序
int i = 0;
int j = 0;
int temp = 0;
for (i = 0; i < numsSize - 1; i++) //BubbleSort共进行n-1趟
{
for (j = 0; j < numsSize - 1 - i; j++) //每一趟比较n-1-i次
{
if (nums[j] > nums[j + 1])
{
temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
//2. 遍历下标和该下标对应的元素
//如果相等,则继续,不相等,输出缺失的数
for (i = 0; i < numsSize; i++)
{
if (i != nums[i])
return i;
}
return numsSize;
}
解法2:
求出前 n+1 个数字之和,在减去数组中的所有数字,就是缺失的数字。
- 求和,计算 0 + 1 + 2 + 3 + 4 + …… + n-1 + n 的值(可用等差数列求和公式)
- 减去数组中值的累加,得到的值就是缺失的数字。
该算法的时间复杂度为:O(N),符合要求。
代码如下:
#include<stdio.h>
int missingNumber(int* nums, int numsSize)
{
//因为缺失了一个,数组nums中只有n个元素,数组元素个数numsSize = n
//1. 求和 0 + 1 + 2 + 3 + 4 + …… + n-1 + n(共n+1项)
//等差数列前 n 项和公式 Sn=n(a1+an)/2
int sum = (numsSize + 1) * (0 + numsSize) / 2;
//2. 减去数组中的所有数
int i = 0;
for (i = 0; i < numsSize; i++)
{
sum -= nums[i];
}
//3. 返回减后的结果
return sum;
}
int main()
{
int nums[9] = { 9,6,4,2,3,5,7,0,1 };
int numsSize = sizeof(nums) / sizeof(nums[0]); //求数组元素个数
printf("missingNumber: %d\n", missingNumber(nums, numsSize)); //求缺失的数
return 0;
}
运行结果:
![image-20210729095610554](https://gitee.com/codewinterll/blog---images/raw/master/img/20210729095610.png)
解法3:
对比观察:0 到 n 的所有整数,以及在此基础上缺失了一个数的数组 nums,有什么特点呢?
异或的两个特性:
两个相等的数异或等于 0
任何一个数和 0 异或之后,还是这个数不变
a ^ a = 0;0 ^ a = a;a ^ a ^ b = b
比如,原数组为:0 1 2 3
缺失一个数的数组:0 1 3
一一异或得到缺失的那个数:0 ^ 1 ^ 2 ^ 3 ^ 0 ^ 1 ^ 3 = 2
-
我们利用异或的特性,两个相等的数异或等于 0,示例1和2的两个数组中除了缺失的那个数,其余数都出现了两次,将它们一起异或,就得到了一个 0,而 0 与缺失的那个数异或,还是等于原来的数。
-
初始化 x = 0,用 x 跟 0 ~ n 的所有数一一异或后,再跟数组 nums 中所有数一一异或,得到结果就是缺失的那个数,该算法的时间复杂度是:O(N),符合要求
代码如下:
int missingNumber(int* nums, int numsSize)
{
//因为缺失了一个,数组nums中只有n个元素,数组元素个数numsSize = n
int i = 0;
int x = 0;
//1. 与 0 ~ n 所有数异或
for (i = 0; i <= numsSize; i++)
{
x ^= i;
}
//2 .再与数组中所有数异或
for (i = 0; i < numsSize; i++)
{
x ^= nums[i];
}
return x;
}
大家赶紧动手去练一练吧!