消失的数字
思路1
将0~n所有整数相加求和后减去这个数组所有元素之和,得到的就是消失的数字
0~n所有元素求和采用等差数列求和公式 Sn = n*(n+1)/2
时间复杂度: O(n)
空间复杂度: O(1)
参考代码
int missingNumber(int* nums, int numsSize){
int N=numsSize;
int ret=N*(N+1)/2; //0~N所有元素之和
for(int i=0;i<numsSize;i++)
{
ret-=nums[i];
}
return ret;
}
思路2
其余所有元素均出现两次。
由单身狗变形到此题: 整数数组其中恰好有1个元素只出现一次其余所有元素均出现两次。
单身狗: 将数组中所有元素异或后得到的就是只出现一次的数字
结论: a^a = 0 , 0^0 = a题解:将数组中所有元素全部异或后,再异或0~n这一组数得到的结果就是消失的数字
时间复杂度: O(n)
空间复杂度: O(1)
参考代码
int missingNumber(int* nums, int numsSize){
int ret=0;
for(int i=0;i<numsSize;i++)
ret^=nums[i];
for(int i=0;i<=numsSize;i++)
ret^=i;
return ret;
}
思路3(不符合题目要求)
将整个数组排序后,比较后一个元素减1是否等于前一个元素,这里采用qsort排序
qsort排序 | 冒泡排序 | |
---|---|---|
时间复杂度: | O(nlogn) | O(n^2) |
空间复杂度: | O(logn) | O(1) |
参考代码
int cmp_int(const void*e1, const void*e2)
{
return (*(int*)e1-*(int*)e2); //排列成升序
}
int missingNumber(int* nums, int numsSize){
qsort(nums,numsSize,sizeof(int),cmp_int);
for(int i=0;i<numsSize-1;i++)
{
//排序完成后,后一个数减1是否等于前一个数
if(nums[i+1] - nums[i] != 1)
{
return nums[i]+1;
}
}
if(nums[0] != 0) //消失的数字是0
{
return 0;
}
else //数组元素个数为n
{
return numsSize;
}
}
轮转数组
思路1
一个元素一个元素旋转
一趟旋转: 先将要旋转的元素保存起来, 后挪动数组元素,最后将存起来的元素放到数组首元素的位置
一共旋转k趟时间复杂度: O(kn),也可以认为是O(n^2)
空间复杂度: O(1)
参考代码
void rotate(int* nums, int numsSize, int k){
if(k>=numsSize)
k%=numsSize;
while(k--)
{
//一趟旋转
int tmp=nums[numsSize-1]; //1.将要旋转的数字存起来
for(int i=numsSize-1;i>0;--i) //2.数组元素整体向后挪
{
nums[i]=nums[i-1];
}
nums[0]=tmp; //3. 要旋转的数挪到数组首元素位置
}
}
思路2
以时间换空间的思想
新开辟一块空间,右旋时,先将要旋转的元素拷贝到前面,再不旋转的元素拷贝到后面,最后整体拷贝回原数组时间复杂度: O(n)
空间复杂度: O(n)
参考代码
void rotate(int* nums, int numsSize, int k){
if(k>=numsSize)
k%=numsSize;
//变长数组
int tmp[numsSize];
//后k个拷贝到前面
int j=0;
for(int i=numsSize-k;i<numsSize;++i)
{
tmp[j++]=nums[i];
}
//前n-k个拷贝到后面
for(int i=0;i<numsSize-k;++i)
{
tmp[j++]=nums[i];
}
//整体拷贝
for(int i=0;i<numsSize;++i)
{
nums[i]=tmp[i];
}
}
思路3
3步翻转法
1.先逆置前n-k个
2.再逆置后k个
3.整体逆置时间复杂度: O(n)
空间复杂度: O(1)
参考代码
void reverse(int*a, int begin, int end)
{
while(begin<end)
{
int tmp=a[begin];
a[begin]=a[end];
a[end]=tmp;
++begin;
--end;
}
}
void rotate(int* nums, int numsSize, int k){
if(k>=numsSize)
k%=numsSize;
reverse(nums,0,numsSize-k-1); //逆置前n-k个
reverse(nums,numsSize-k,numsSize-1); //逆置后k个
reverse(nums,0, numsSize-1); //整体逆置
}