赞
踩
对于该题,最能想到应该有四种方法:
1. 排序
可以将元素排序好,再遍历一遍数组看后一个是否是前一个元素的值+1,但是从对于初学者掌握的无非就是冒泡排序或者qsort
很遗憾,虽然但是,不满足题目的时间复杂为O(n),因为冒泡排序的时间复杂度为O(n^2),qsort的时间复杂度为O(nlogn)因此,因此不行
2. 映射
开辟一个数组并初始化为-1(因为有0的存在),把对应的数字放入对应的数组下标所对应的数组元素中,然后再遍历一遍数组,出现负数的那个元素则为缺少的数字
很遗憾,虽然但是,要使用数组开辟空间,空间复杂度为O(n),因此不行
3. 使用操作符 ^
使用异或操作符,利用它的两个特性,同样的数字异或以后为0,不论顺序,一个数字与0异或为本身,空间复杂度O(1),时间复杂度为O(n)
所以可以!附上代码
- int missingNumber(int* nums, int numsSize) {
- int i = 0;
- int temp = 0;
-
- //先和数组异或
- for (i = 0; i < numsSize; i++)
- {
- temp ^= nums[i];
- }
-
- //再和0~n的数字异或,就得到缺少的数字
- for (i = 0; i <= numsSize; i++)
- {
- temp ^= i;
- }
-
- return temp;
- }
4. 等差数列
因为是0~n的数字,因此,这是一个等差数列,所以先把0~n的数字求和,再减去数组中的所有元素,剩下的数字即为所缺数字,时间复杂为O(n),空间复杂度为O(1),因此可行,附上代码
- int missingNumber(int* nums, int numsSize) {
- int i = 0;
- //等差数列求和
- int Sn = ((0 + (numsSize)) * (numsSize + 1)) / 2;
- //减去数组中的每个值,即剩下的就是缺少值
- for (i = 0; i < numsSize; i++)
- {
- Sn -= nums[i];
- }
- return Sn;
- }
题目要求至少三种方法,这道题最容易能想到能想到两种,第三种不太好想到
1. 右旋k次,依次移一个
先把数组最后一个元素先给放到一个临时变量temp中,然后将数组中的元素从第一个开始依次往后赋值,最后将temp中的值赋给第一个元素,即完成了一次的右旋,右旋k次即按这个思路进行k次
这个方法的空间复杂度是O(1), 但是,时间复杂度是O(n*k),为什么是k呢?
因为这种情况最好的结果是k=1,但是最坏的结果却是要旋转n-1次(k % N = N - 1),也就是说,时间复杂度最差能到O(n^2),受k影响过大,所以用k最好
很遗憾,虽然但是,这种方法leetcode不给过,时间超出限制,时间复杂度太差!
2. 额外开数组
开过个数组,然后把k个元素放过去,很简单
很遗憾,虽然但是,空间复杂度和时间复杂度都是O(n),不满足要求!
3. 逆置三次
前N~K个元素逆置,后K个逆置,然后整体逆置
时间复杂度为O(n),空间复杂度为O(1),满足
代码如下
- void reverse(int* nums, int left, int right)
- {
- while(left < right)
- {
- int temp = nums[left];
- nums[left] = nums[right];
- nums[right] = temp;
- ++left;
- --right;
- }
- }
-
-
- void rotate(int* nums, int numsSize, int k){
- //防越界
- k %= numsSize;
- //前面部分逆置
- reverse(nums, 0, numsSize-k-1);
- //后面部分逆置
- reverse(nums, numsSize-k, numsSize-1);
- //全部逆置
- reverse(nums, 0, numsSize-1);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。