leetcode每日一题——189.轮转数组(面试经典150题)

一、题目描述与要求

189. 轮转数组 - 力扣(LeetCode)

题目描述

给定一个整数数组 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

二、解题思路

总的思路:

       对题目进行分析可知,我们需要根据轮转量k,将数组后面的k个元素按照原来的顺序放到前面去,而原本前面的元素则按顺序往后移动。例如k=1,数组元素为1234567,那么轮转后的结果应改为5671234。

       要实现这一过程,首先最简单的就是直接利用另一个数组,将原本数组里面的元素按照轮转后的顺序存放到辅助数组里面,然后再将辅助数组的值赋值给数组即可。其中元素轮转后所对应的位置可以由(i+k)%numsSize得到。这一方法的时间复杂度为O(n),空间复杂度也为O(n)。有没有办法能够减少所利用的空间复杂度呢?因为当数组元素过大时,就需要很大的辅助空间。

       我们观察1234  567和567  1234,可以发现轮转相当于根据k的值把数组后面k个元素放到前面,因此我们也可以直接把这个数组分成两部分,分成两部分后怎么让它按照对应的顺序呢,很显然先分成两部分是很难实现排成对应的顺序。那我们想,后面k个元素是要放到前面的,而前面的元素要放到后面去,那我们不如直接先将数组进行翻转,也就是变成“逆序”。然后再把数组分成两部分,此时每一部分所包含的元素是正确的,只是顺序不正确,因为我们对其进行了一次翻转排序,因而只需要分别对两部分再次进行翻转即可。

具体步骤:

利用辅助数组:

①定义辅助数组

②按目标为辅助数组赋值

③利用辅助数组更新原有数组

数组翻转:【在原数组上进行改动】

①判断轮转量是否大于数组元素,若大于则要取余数(因为没那么多位进行轮转)

②对整个数组进行翻转(利用双指针实现首尾元素交换)

③对翻转后的数组的前k个元素进行翻转

④对翻转后的数组的后半部分进行翻转


三、具体代码【C语言】

① 利用辅助数组  【时间O(n)  空间O(n)】

void rotate(int* nums, int numsSize, int k){
    if( k ==0 || numsSize == 1)   return;
    int tem[numsSize];//定义辅助数组
    for(int i=0;i<numsSize;i++){
        tem[(i+k)%numsSize]=nums[i];//在辅助数组中将每一个元素放到对应位置
    }
    for(int i=0;i<numsSize;i++){//复制数组
        nums[i]=tem[i];
    }
}

数组翻转:【在原数组上进行改动】 【时间O(n)  空间O(1)】

void swap(int* a, int* b) //传址
{
    int t = *a;
    *a = *b;
    *b = t;
}

void reverse(int* nums, int left, int right) //对数组进行翻转
{
    while (left < right) 
    {
        swap(&nums[left], &nums[right]);//将首尾两个数进行交换
        left += 1;
        right -= 1;
    }
}

void rotate(int* nums, int numsSize, int k){
    k%=numsSize;  //避免出现轮转量大于数组元素的情况
    if( k ==0 || numsSize == 1)   return;
    //翻转整个数组
    reverse(nums, 0, numsSize - 1);
    //将翻转后的前面部分变回原始顺序
    reverse(nums, 0, k - 1);
    //将翻转后的后面部分变回原始顺序
    reverse(nums, k, numsSize - 1);
}

猜你喜欢

转载自blog.csdn.net/m0_59800431/article/details/131551454