【leetcode之189. 轮转数组】详解

文章详细介绍了LeetCode第189题的解决方案,包括创建新数组、数组翻转和环形替换三种方法,重点讨论了它们的时间复杂度和内存消耗。第一种方法虽然直观但消耗额外空间,后两种方法优化了空间复杂度,特别是第三种方法在时间和空间上都较优。
摘要由CSDN通过智能技术生成


原题

链接:https://leetcode.cn/problems/rotate-array/:

在这里插入图片描述
很有意思的一道题,本人提供三种方法,有更巧妙的方法的同学欢迎交流


正文开始

一、Create a new array

创建一个新数组,拿新数组进行(i+k)%numsize=i进行元素的偏移以达到题目目的,
再把新数组赋值给原先数组
图解:
在这里插入图片描述
在这里插入图片描述
代码实现:

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

该方法时间复杂度为O(N),该方法创建了一个新数组,消耗内存,下面两种方法可以进一步优化

二、Array flipping

这个方法极奇难以想到,但是你见过一次就难以忘怀。
思路:

  1. 将整个数组翻转
  2. 将翻转后的数组从第0个到第k-1个翻转
  3. 将翻转后的数组从第k个到第numsize个翻转
    图解如下
    在这里插入图片描述
    在这里插入图片描述
    代码实现:
void swap(int* a, int* b) {
    int t = *a;
    *a = *b, *b = t;
}

void reverse(int* nums, int start, int end) {
    while (start < end) {
        swap(&nums[start], &nums[end]);
        start += 1;
        end -= 1;
    }
}

void rotate(int* nums, int numsSize, int k) {
    k %= numsSize;
    reverse(nums, 0, numsSize - 1);
    reverse(nums, 0, k - 1);
    reverse(nums, k, numsSize - 1);
}

三.Ring substitution

解题技巧:

  • 我们可以把数组看成一个圆环,只要访问数组下标超过numsize就对numsize取余
  • 因为把一个元素i向后挪k个位置,那么第(i+k-1)个位置的元素势必被覆盖,故我们想到使用一个中间变量接收,然后再进行中间变量和第(i+k-1)进行交换,使中间变量不断后移。
  • 直到中间变量等与从开始的元素相等,第一次轮转结束
    图解:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    得到结果
    代码实现:
void swap(int* a, int* b)
{
    int t;
    t = *a;
    *a = *b;
    *b = t;
}
void rotate(int* nums, int numsSize, int k)
{
    int cnt = 0;
    int temp, p;
    for (int start = 0; start < numsSize; start++)
    {
        temp = nums[start];
        p = start;
        do
        {
            p = (p + k) % numsSize;
            swap(&temp, &nums[p]);
            cnt++;
        } while (p != start);
        if (cnt == numsSize) break;
    }

}

执行结果:
在这里插入图片描述
该方法时间复杂度为O(1),内存消耗较小,效率较高

总结

第一种方法各位务必要掌握
第二种和第三种了解仅可

一天不力扣我就浑身难受。

                                      --莎士比亚
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

江财菊圃路彭家桥C++一霸

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

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

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

打赏作者

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

抵扣说明:

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

余额充值