数组nums包含从0到n的所有整数,但是其中缺了一个。请编写代码找出那个缺失的整数。要求:时间复杂度O(n)。
//第一次尝试: //方法一:思路是再开辟一个numsSize+1的数组arr,然后遍历nums,出现的数字在arr下标对应的位置设为-1,然后遍历arr,没有出现-1的,就是消失的数字 //方法二:思路是将nums中的数相加得到sum,然后从0加到numsSize,得到sum1,然后sum1-sum=ret,则ret就是消失的数字。
//方法三:异或法,我们知道异或的性质,相同异或为0,相异异或为1,所以我们可以将0到numsSize的数全员异或,以及将nums[0]到nums[numsSize-1]的数全员异或一遍,
// 那么没出现的数字将会只异或了一遍,而其他数字都异或了两遍,所以其他数字都抵消了,只剩下了没出现的数字
#include<stdio.h> #include<stdlib.h> //时间复杂度:O(n) int missingNumber1(int* nums, int numsSize) { int* arr = (int*)calloc(numsSize + 1, sizeof(int)); if (arr == NULL) return NULL; for (int i = 0; i < numsSize; i++) { arr[nums[i]] = 1; } for (int i = 0; i < numsSize + 1; i++) { if (arr[i] == 0) return i; } } //这个做法中动态开辟了一块内存,虽然没有释放,但是程序瞬间就执行结束了,然后会由系统会自动释放,所以不会造成内存泄露,但是在实际开发中一定不要这么做,会出问题的 //你可以将动态开辟这一步封装成函数,得到需要的结果后释放掉空间,然后返回结果 //时间复杂度:O(n) int missingNumber2(int* nums, int numsSize) { int sum = 0, sum1 = 0; for (int i = 0; i < numsSize; i++) { sum += nums[i]; sum1 += i; } //上面只循环了numsSize-1次,所以要多加个numsSize sum1 += numsSize; return sum1 - sum; } //异或法 int missingNumber3(int* nums, int numsSize) { int ret = 0; for (int i = 0; i < numsSize; i++) {
//全员异或 ret ^= i; ret ^= nums[i]; }
//循环中没有异或到numsSize这个数 ret ^= numsSize; return ret; } int main() { int arr[] = { 8,6,4,2,3,5,9,0,1 }; printf("%d\n", missingNumber1(arr, sizeof(arr) / sizeof(arr[0]))); printf("%d\n", missingNumber2(arr, sizeof(arr) / sizeof(arr[0]))); return 0; }
浙公网安备 33010602011771号