经典题目----轮转数组

题目描述

点击跳转到Leetcode----轮转数组
在这里插入图片描述

解题方法

原地倒置:

  基本思路是先把前 n-k 个元素倒置(倒序排列),以实例一且为例,变成了4 3 2 1 5 6 7 。
  然后把后k个元素倒置,变成了 4 3 2 1 7 6 5 。
  最后整体倒置,变成了 5 6 7 1 2 3 4 ,达到了目的。

  这个方法不是很好想,需要大量观察规律才能看出来
代码:

void reverse(int* nums,int begin,int end){
	while(begin < end){
        int tmp=nums[begin];
        nums[begin]=nums[end];
        nums[end]=tmp;
        begin++;
        end--;
    }
}
void rotate(int* nums,int numSize,int k){
    reverse(nums,0,numSize-k-1);//倒置前n-k个
    reverse(nums,numSize-k,numSize-1);//倒置后k个
    reverse(nums,0,numSize-1);//倒置整体
}

  需要注意的是下标不要写错,因为数组下标从0开始而 numSize 和 k 都是数量,不是下标。

  但是没有对参数进行检查,容易出现BUG,比如如果 k 大于数组元素个数就无法处理了,所以倒置前要先处理k的值,完整代码是:

void reverse(int* nums,int begin,int end){
    assert(nums);
	while(begin < end){
        int tmp=nums[begin];
        nums[begin]=nums[end];
        nums[end]=tmp;
        begin++;
        end--;
    }
}
void rotate(int* nums,int numSize,int k){
    assert(nums);
    //k应该小于numSize
    if(k >= numSize){
        k %= numSize;
    }
    reverse(nums,0,numSize-k-1);//倒置前n-k个
    reverse(nums,numSize-k,numSize-1);//倒置后k个
    reverse(nums,0,numSize-1);//倒置整体
}

  它的时间复杂度是O(N),能够通过这道题。

  关于它的空间复杂度,由于是原地倒置,额外开辟的空间只有tmp,所以空间复杂度为O(1)。

用空间换取时间:

  用另外一个数组充当媒介,把后k个数拷贝到另外一个数组的前k个,把前n-k个数拷贝到后n-k个,最后把这个数组的数据拷回原数组,这样虽然空间复杂度比第一个方法大,但是时间比暴力求解快,属于是拿空间换取时间了。

void rotate(int* nums, int numsSize, int k){
    //检查参数k
    if(k>=numsSize){
        k%=numsSize;
    }

    int* tmp=(int*)malloc(sizeof(int) * numsSize);
    memcpy(tmp,nums+numsSize-k,sizeof(int)*k);//把后k个拷到新数组的前k个
    memcpy(tmp+k,nums,sizeof(int)*(numsSize-k));//把前n-k个拷到新数组的后n-k个
    memcpy(nums,tmp,sizeof(int)*numsSize);//把数据拷回原数组
    free(tmp);
    tmp=NULL;
}

这个方法的时间复杂度是O(N),memcpy内部是一个字节一个字节拷贝,循环的次数是元素个数的常数倍,所以它的时间复杂度为O(N)。

空间复杂度是O(N),因为用malloc申请了numSize个字节的空间。

传统思路,暴力求解:

  传统的思路是一步一步移,先把7保存下来,然后让123456一个一个往后移,这样移一次是O(N),但题目不是移一个,而是K个,所以这样的方法时间复杂度就是O(K*N),最坏情况下K是N-1,因为K=N的时候相当于没有移动,所以这个方法的时间复杂度是O(N2),比O(N)大,在Leetcode上不能通过全部的测试用例。
在这里插入图片描述
  忽略时间上的限制的话,这种方法能解决问题,代码:

void rotate(int* nums, int numsSize, int k){
    int i=0;
    while(k--){
        int  tmp=nums[numsSize-1];
        for(i=numsSize-1;i>0;i--){
            nums[i]=nums[i-1];
        }
        nums[0]=tmp;
    }
}

本文完。
                (如果文章有错误之处,请在评论区点醒作者,谢谢!)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嫋嫋.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值