【LeetCode】轮转数组

【LeetCode】轮转数组_第1张图片

内容专栏:《LeetCode刷题专栏》

本文概括:189.轮转数组

本文作者:花 碟

发布时间:2023.4.12

目录

思想1 暴力求解

代码实现:

思想2 三次倒置

代码实现: 

思想3 memcpy零时拷贝

代码实现:


189.轮转数组 点击跳转到LeetCode平台OJ页面

题目:​​​​​​​

给定一个整数数组 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 暴力求解

从右边开始,每轮移动一次,移动k轮,但是这种解法最坏的情况是k等于numsSize - 1,每轮又要移动numsSize - 1次。时间复杂度为O(k*n),或者说是O(n^2)

画图分析: 

【LeetCode】轮转数组_第2张图片 

代码实现:

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

我们以这种方法去写固然可行,但是放入leetcode之中,再去提交的时候,只通过了37/38个测试用例,leetcode检测过于严格,通过不了,那么这种方式去写就不太合适了,有没有更加好的解法思想呢?我们往下看。

思想2 三次倒置

第1步.我们从k处分隔数组,分为左右两边,各自进行倒置即可;

第2步.对整个数组进行倒置,这样子就会让最开始想要翻转的数组个数挪动到前面了。

注⚠️:也可以先进行第二步,再进行第1步,此方法无先后顺序,最终都能达到效果。

画图分析: 

【LeetCode】轮转数组_第3张图片

【LeetCode】轮转数组_第4张图片

注⚠️: k 必须要保证小于numsSize,否则提交代码会出现以上图片中的执行错误,原因是数组出现越界,将执行结果,numsSize为1,k = 2,代入第一个reverse函数,结果为-1,故会出现数组越界,此外,k需要避免过大,进行多次无效的重复运算,以示例1为例,数组翻转8次就相当于数组翻转1次。

【LeetCode】轮转数组_第5张图片

代码实现: 

void reverse(int* nums,int left,int right)
{
    while(left < right)
    {
        int tmp = nums[left];
        nums[left] = nums[right];
        nums[right] = tmp;
        left++;
        right--;
    }
}
void rotate(int* nums, int numsSize, int k){
   if(k > numsSize)
   {
       k %= numsSize;//去掉if条件判断也行
   }
    reverse(nums,numsSize - k,numsSize - 1);//右边倒置
    reverse(nums,0,numsSize - k - 1);//左边倒置
    reverse(nums,0,numsSize - 1);//整体倒置
}

思想3 memcpy拷贝数组

我们利用malloc申请一块为numsSize元素*int类型大小的内存空间,我们从k处分隔原数组,利用memcpy函数先将后面的k个元素拷贝到内存空间,再次将前numsSize - k个元素拷贝到k个元素的后面,最后将内存空间的numsSize*sizeof(int)个字节空间拷贝到原数组之中。

memcpy函数不熟悉的小伙伴,这里放出库函数的使用规则,更详细内容,可以在cplusplus 官网进行搜索查看哦【LeetCode】轮转数组_第6张图片

代码实现:

void rotate(int* nums, int numsSize, int k){
   if(k > numsSize)
   {
       k %= numsSize;
   }
   int* tmp = (int*)malloc(sizeof(int) * numsSize);
   memcpy(tmp,nums + numsSize - k,sizeof(int) * k);
   memcpy(tmp + k,nums,(numsSize - k) * sizeof(int));
   memcpy(nums,tmp,sizeof(int) * numsSize);
   //
   free(tmp);
   //tmp = NULL
}

 


  这篇文章就到此为止了,如果对你有帮助,还请多多支持博主哦~~

你可能感兴趣的:(LeetCode刷题,leetcode,算法,c++,C语言)