前言:这里是数据结构习题的整合,一直会更新!
目录:
1.消失的数字
1.数组
nums
包含从0
到n
的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?注意:本题相对书上原题稍作改动
方法1:qsort排序(不满足题意,时间复杂度为O(N*logN))
思路:使用qsort排序,然后依次查找,如果下一个数不是上一个数+1,那么上一个数+1就是消失的数字。
//1.使用C语言库函数qsort()排序,这样数字就和数组下标相对应; //2.然后遍历数组nums,用nums[ i+1 ] - nums[ i ] 判断,等于1表示两个数相邻,等于2表示缺失了的那个数; //3.把对应的下标 i+1 输出即可 #include <stdio.h> #include <stdlib.h> int compare(const void *a, const void *b) { return (*(int*)a - *(int*)b); } int findMissingNumber(int nums[], int n) { qsort(nums, n, sizeof(nums[0]), compare); for (int i = 0; i < n - 1; i++) { if (nums[i + 1] - nums[i] > 1) { return nums[i] + 1; } } return n; } int main() { int nums[] = {1, 3, 0, 2, 5}; int n = sizeof(nums) / sizeof(nums[0]); int missingNumber = findMissingNumber(nums, n); printf("Missing number: %d\n", missingNumber); return 0; }
方法2:求和作差
思路:对完整的0-n求和后与缺失后的数组的和作差,得到的结果即为消失的数字
//等差数列求前n项和的公式为:Sn=n*(n+1)/2 //求完和之后,减去nums数组中的所有的值 int missingNumber(int* nums, int numsSize) { size_t i=0; int x=numsSize*(1+numsSize)/2; for(i=0;i<numsSize;i++) { x-=nums[i]; } return x; } //或者分别求和,然后相减,核心都是一样的
方法3:异或运算
思路:异或运算相同为0,0与任意数异或结果为任意数。
- 0^x = x;
- x^x = 0; 同样的数异或两次得到零
- 异或满足交换律
//先异或[0,n]的所有数字将结果并入x中,再异或nums数字的所有数字进行抵消 int missingNumber(int* nums, int numsSize) { int x = 0; for (int i = 0; i < numsSize+1; i++) { x ^= i;//x^1^2^3.... } for (int i = 0; i < numsSize; i++) { x ^= nums[i];//x^1^1^2^2^3.... } return x; }
另外还有哈希表的方法,暂时先不展示。
2.轮转数组
跳转链接
2.给定一个整数数组
nums
,将数组中的元素向右轮转k
个位置,其中k
是非负数。
1.暴力求解,旋转k次
注意:这里如果k是n的话,就没必要旋转(所有数都旋转了一次)
void rotate(int* nums, int numsSize, int k){ if(k>=numsSize) { k%=numsSize; } for(int i=1;i<=k;i++) { int tmp=nums[numsSize-1]; for(int s=numsSize-1;s>0;s--) { nums[s]=nums[s-1]; } nums[0]=tmp; } }
时间复杂度为O(N^2),空间复杂度为O(1),(时间效率低)
2.三段逆置
void resever(int* nums,int left,int right) { while(left<right) { int tmp=nums[right]; nums[right]=nums[left]; nums[left]=tmp; left++; right--; } } void rotate(int* nums, int numsSize, int k) { if(k>=numsSize) { k%=numsSize;//k小于numsSize时,不会访问越界 } resever(nums,0,numsSize-k-1);//0,n-k-1 resever(nums,numsSize-k,numsSize-1);//n-k,n-1 resever(nums,0,numsSize-1);//0,n-1 }
时间复杂度为O(N);空间复杂度为O(1)
3.空间换时间
void rotate(int* nums, int numsSize, int k){ int* tmp = (int*)malloc(sizeof(int) * numsSize); if(k>=numsSize) { k%=numsSize; } for(int i=0;i<k;i++) { tmp[i]=nums[numsSize-k+i]; } for(int i=0;i<numsSize-k;i++) { tmp[i+k]=nums[i]; } for(int i=0;i<numsSize;i++) { nums[i]=tmp[i]; } free(tmp); }
或者
void rotate(int* nums, int numsSize, int k){ if(k>numsSize) k %=numsSize; int *tmp=(int*)malloc(sizeof(int)*numsSize); memcpy(tmp+k,nums,sizeof(int)*(numsSize-k)); memcpy(tmp,nums+numsSize-k,sizeof(int)*(k)); memcpy(nums,tmp,sizeof(int)*numsSize); free(tmp); tmp=NULL; }
时间复杂度为O(N),空间复杂度为O(N)