【LeedCode刷题】轮转数组

目录

1、题目描述

2、方法一

3、方法二

4、方法三(三步逆置法)


1、题目描述

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

输入: 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、方法一

循环k次,每一轮循环保存数组最后面的元素,然后前n-1个元素往后移一位,最后再把最后一个元素放到nums[0]的位置

但是这个方法的时间复杂度过高,是O(N^2),而不是O(k*n)

因为k和n之间是有关系的(k可以分最好情况和最坏情况),当最好时,k是n的倍数根本不用轮转,时间复杂度为O(1)

最坏是k=n-1时,此时时间复杂度是O(N^2),此时空间复杂度是O(1)

注意此时是过不去OJ的,因为时间复杂度过高。

【LeedCode刷题】轮转数组_第1张图片

void rotate(int* nums, int numsSize, int k) {
    k%=numsSize;//k要%是因为,防止k大于numsSize造成重复轮转或k==numsSize,不需要轮转
    while(k--)
    {
        int tmp = nums[numsSize-1];
        for(int i = numsSize-2;i>=0;i--)
        {
            nums[i+1]=nums[i];
        }
        nums[0]=tmp;
    }
}

3、方法二

观察输入与输出会发现,轮转就是将后k个元素放到前面,前n-k个放到后面。

开辟一个与原数组大小相同的数组,然后先将原数组的后k个数拷贝到新开辟数组的前k个位置

然后将原数组的前n-k个元素拷贝到新开辟数组的后n-k个位置,然后将新开辟数组的元素全部拷贝回原数组

此时时间复杂度O(n),空间复杂度O(n)

【LeedCode刷题】轮转数组_第2张图片

void rotate(int* nums, int numsSize, int k) {
    k%=numsSize;
    int* tmp = (int*)malloc(sizeof(int)*numsSize);
    int n = numsSize;
    memcpy(tmp,nums+n-k,sizeof(int)*k);
    memcpy(tmp+k,nums,sizeof(int)*(n-k));
    memcpy(nums,tmp,sizeof(int)*n);
}

 4、方法三(三步逆置法)

三步逆置法

先将前n-k个逆置,再将后k个逆置,最后再整体逆置

时间复杂度O(n),空间复杂度O(1)

【LeedCode刷题】轮转数组_第3张图片

void Reverse(int* a,int left,int right)//是对[left,right]逆置,左闭右闭
{
    while(left

你可能感兴趣的:(算法,leetcode,c语言,数据结构)