题目:
暴力解法(超时):
第一个想到的应该都是暴力解法,也就是每次都将数组除了最后一个元素都整体往后移一位,然后将刚才的最后一个元素放到第一个位置
就拿题目的用例一来举例
代码如下
void qianyi(int* nums,int n)
{
int i;
for(i=n-1;i>=0;i--)
{
nums[i+1]=nums[i];
}
}
void rotate(int* nums, int numsSize, int k)
{
int i,tmp;
for(i=0;i<k;i++)
{
tmp=nums[numsSize-1];
qianyi(nums,numsSize-1);
nums[0]=tmp;
}
}
然而这个算法的时间复杂度是O(K*N),会导致超时
解法一:翻转数组:
这里开始正式说解法,还是拿上面的示例一来说,可以以k=3为依据分成如图所示,即前n-k个和后k个元素
先将前n-k个元素(也就是[0,n-k])翻转
再将后k个元素翻转
最后将整个数组再翻转,就得到最终结果了
代码如下
void resverse(int *nums,int left,int right)//翻转数组
{
int tmp,i;
while(left<right)
{
tmp=nums[left];
nums[left]=nums[right];
nums[right]=tmp;
left++;
right--;
}
}
void rotate(int* nums, int numsSize, int k)
{
k%=numsSize;
resverse(nums,0,numsSize-1-k);//翻转前n-k个元素
resverse(nums,numsSize-k,numsSize-1);//翻转后k个元素
resverse(nums,0,numsSize-1);//翻转整个数组
}
解法二:空间换时间(再开辟一个数组):
还是拿上面的示例一来举例,一样先给数组分成两个部分,我们可以再开一个和原数组大小一致的数组
先将最后k个元素移过来
再将前n-k个元素移过来
但最后数据是要在原数组的,所以要再把tmp中的数据复制到arr,这样就完成了
但如果只是这样的话还有个小bug,如果k是10呢?k比数组的大小还要大该怎么办?
如果k等于原数组大小的话就相当于没动.
拿示例一来举例,如果k=7,翻转了7次,那就最后还是等于原来的数组
所以要将k%=numsSize,这样可以保证k<numsSize
代码如下
void rotate(int* nums, int numsSize, int k)
{
int *tmp=(int*)malloc(sizeof(int)*numsSize);//开辟一个和原数组同样大小的新数组
k%=numsSize;//确保k<numsSize
int i,j=0;
for(i=numsSize-k;i<numsSize;i++)//将后k个元素移到新数组
tmp[j++]=nums[i];
for(i=0;i<numsSize-k;i++)//将前n-k个元素移到新数组
tmp[j++]=nums[i];
for(i=0;i<numsSize;i++)//将新数组的数据复制到原数组
nums[i]=tmp[i];
}