目录
1、题目描述
2、方法一
3、方法二
4、方法三(三步逆置法)
给定一个整数数组
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]
循环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的,因为时间复杂度过高。
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;
}
}
观察输入与输出会发现,轮转就是将后k个元素放到前面,前n-k个放到后面。
开辟一个与原数组大小相同的数组,然后先将原数组的后k个数拷贝到新开辟数组的前k个位置
然后将原数组的前n-k个元素拷贝到新开辟数组的后n-k个位置,然后将新开辟数组的元素全部拷贝回原数组
此时时间复杂度O(n),空间复杂度O(n)
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);
}
三步逆置法
先将前n-k个逆置,再将后k个逆置,最后再整体逆置
时间复杂度O(n),空间复杂度O(1)
void Reverse(int* a,int left,int right)//是对[left,right]逆置,左闭右闭
{
while(left