一、题目简述
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。例如:
输入:nums=[1,3,5,6,4,1,2,5] ,numsSize=8
k=3
输出:nums=[1,2,5,1,3,5,6,4]
二、方法分析
方法一:
将nums最后一个元素取出,tmp=nums[numSize]
将数组nums向后移动一位,nums[j+1]=nums[j]
将tmp给nums第一个元素,nums[0]=tmp
重复上述过程k次,while(k–)
时间复杂度:O(n^2)
方法二:
将nums数组最后k个元素逆置,numSize-k到numSize-1
将nums数组前numSize-k个数逆置,0到numSize-k-1
再将整个数组逆置即可,0到numSize-1
例如:
nums=[1,3,5,6,4,1,2,5] ,numsSize=8
k=3
逆置最后3个元素:
nums=[1,3,5,6,4,5,2,1]
逆置前五个元素:
nums=[4,6,5,3,1,5,2,1]
逆置整个数组:
nums=[1,2,5,1,3,5,6,4]
本题采用第二种方法更为简便,只需一个逆置函数即可
三、代码分析
1、处理k的范围
k%=numsSize;//将取余
如果将数组向右轮转numSize(数组长度)次,那么nums还是保持原样;所以如果向右轮转 n*numSize+m次,那么相当于向右轮转m次。0<=m<=numSize-1,n为正整数。
所以对k%=numSize,保证0<=k<=numSize-1,也防止数组的越界
2、逆置函数
void reverse(int* nums,int left,int right)
{
while(left<right)
{
int tmp=nums[left];
nums[left]=nums[right];
nums[right]=tmp;
left++;
right--;
}
}
left代表左边的位置,right代表右边位置,同时向中间移动,进行交换,即可完成数组逆置函数。
3、实现右轮转
int left=0;
int right=numsSize-k-1;
reverse(nums,left,right);//逆置前numSize-k个元素
将前numSize-k个元素进行逆置,调用写好的reverse函数。
left=numsSize-k;
right=numsSize-1;
reverse(nums,left,right);//逆置后k个元素
将后k个元素进行逆置,调用写好的reverse函数。
left=0;
right=numsSize-1;
reverse(nums,left,right);//逆置整个数组
逆置整个数组,调用写好的reverse函数。
四、完整代码
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) {
k%=numsSize;//保证0<=k<=numSize-1
int tmp=0;
int left=0;
int right=numsSize-k-1;
reverse(nums,left,right);//逆置前numSize-k个元素
left=numsSize-k;
right=numsSize-1;
reverse(nums,left,right);逆置后k个元素
left=0;
right=numsSize-1;
reverse(nums,left,right);//逆置整个数组
}