leetcode刷题1

消失的数字

链接

在这里插入图片描述

思路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);              //整体逆置
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值