//复杂度表示方法:
//训练题1:消失的数字
//数组nums包含从0~numsSize的所有整数,但其中缺了一个。请编写代码在O(N)时间内完成
//思路一:先排序,再比较
//不可行,冒泡O(N^2),qsort(快排)O(n*logn)----->都不可行
//思路二:计算0~n的所有数字和,再减去数组中的每个数据,剩下的数字就是缺了的数据
//缺陷:所有数字和太大,存在溢出风险
int missingNumber(int* nums, int numsSize){
int n=numsSize;
int sum=(numsSize+1)*(0+n)/2;
for(int i=0;i<n;i++)
{
sum-=nums[i];
}
return sum;
}
//思路三:异或,相同为零,相异为一
//把数字展开成二进制的形式,每个二进制位出现了两个1就会归0,最后每一个二进制位剩下的数字1算出来就是那个只出现一次的数字。0和所有数字异或都等于那个数字
//注意两个for循环循环的次数不一样
int missingNumber(int* nums, int numsSize){
int n=0;
for(int i=0;i<numsSize;i++)
{
n^=nums[i];
}
for(int i=0;i<=numsSize;i++)
{
n^=i;
}
return n;
}
//训练题2:轮转数字
//思路一:使用普通的O(N^2)算法,会超时!!!
void rotate(int* nums, int numsSize, int k) {
k%=numsSize;//注意当为7的倍数时数组不变;
while(k--)
{
int tmp=nums[numsSize-1];
for(int i=numsSize-2;i>=0;i--)
{
nums[i+1]=nums[i];
}
nums[0]=tmp;
}
}
//思路二:
void reverse(int *a,int j,int k)
{
int left=j;
int right=k;
while(left<right)
{
int tmp=a[left];
a[left]=a[right];
a[right]=tmp;
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);
}
//注意:reverse函数可以不用返回数组指针,因为传的是指针,直接就改变了原数组
//没有空间复杂度限制的时候可以新开辟一块空间,先拷贝后面逆置的那一块数据,再把前面那块数据拷贝进去
//拓展:二分查找(两种写法)
//递归时间复杂度:所有递归调用次数累加
//规律:N-(2的几次方)=进入的第几层Fib(即Fib()括号中的数字)
//错位相减法
//改进方法:把递归变循环//时间复杂度变为O(N)
//~空间复杂度
//以空间换时间,时间O(N),空间O(N)
void reverse(int *a,int n,int k)
{//从哪个点开始,拷贝几个数据
int *tmp=(int*)malloc(sizeof(int)*n);
memcpy(tmp,a+n-k,sizeof(int)*(k));
memcpy(tmp+k,a,sizeof(int)*(n-k));
memcpy(a,tmp,sizeof(int)*n);
}
void rotate(int* nums, int numsSize, int k) {
k%=numsSize;
reverse(nums,numsSize,k);
}