LeetCode每日精进:189.轮转数组

题目链接:189.轮转数组

题目描述:

        给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

示例 2:

输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

提示:

  • 1 <= nums.length <= 105
  • -231 <= nums[i] <= 231 - 1
  • 0 <= k <= 105

思路一:

         先保存下标numsSize - 1的元素,将前numsSize - 1个元素往后移动一位,最后将保存的元素放在数组第一个位置。

代码实现:

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

分析:                

        由于这里存在双循环,时间复杂度为O(n^2),空间复杂度O(1),还需要继续优化思路。

思路二:创建新数组

        在这里,用malloc动态申请一个新数组arr,用来存放轮转后的数组,将原数组中的下标为i的元素放在arr中下标为(i+k)%numsSize的位置,这里%numsSize的原因时i+k在遇到要向右轮转的元素时会超出numsSize,这里直接让其重新回到数组头部。

        由于函数返回的是数组nums,最后再将arr中的元素复制到nums即可。

代码实现:

void rotate(int* nums, int numsSize, int k) {
    int* arr = (int*)malloc(numsSize*sizeof(int));
    for (int i = 0;i<numsSize;i++)
    {
        arr[(i+k)%numsSize] = nums[i];
    }
    for (int i = 0;i<numsSize;i++)
    {
        nums[i] = arr[i];
    }
}

分析:

        代码中用了两个循环,时间复杂度为O(n),相较于思路一,运行时间缩短,但相较于思路一,空间复杂度提升到了O(n),这是一种时间换空间的方法,那么是否有办法让空间复杂度降为O(1)呢?

思路三:三次逆置

        依旧以轮转三次为例:       

        第一次逆置:将前n-k个数据逆置

        第二次逆置:将后k个数据逆置

        第三次逆置:整体逆置

void reverse(int* nums,int left,int right)
{
    while(left < right)
    {
        int tmp = nums[left];
        nums[left] = nums[right];
        nums[right] = tmp;
        left++;
        right--;
    }
}

        由于需要用到三次逆置,为了不让代码冗余,这里我们封装一个用来逆置的函数,参数为数组,数组中需要逆置的部分的头部和尾部的下标。

k %= numsSize;

         若k值超过了numsSize,那么数组会重复轮转,所以我们这里模上一个numsSize。

代码实现:

void rotate(int* nums, int numsSize, int k) {
    k %= numsSize;
    //三次逆置
    //前numsSize-k个数据逆置
    reverse(nums,0,numsSize-k-1);
    //后k个数据逆置
    reverse(nums,numsSize-k,numsSize-1);
    //整体逆置
    reverse(nums,0,numsSize-1);
}   

分析:

        思路三中,空间复杂度降为了O(1)时间复杂度依旧为O(n),在思路二的基础上再次进行了优化,不再借助新数组,实现了一个较为完善的方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值