题目概述
题目示例
题目解读
这虽然是一道算法题,但是明面没有对时空复杂度提出要求,给我们的操作空间就比较大(菜鸡狂喜,嘿嘿),这样就有两个简单的解法;
解法一:构建两层循环,直接在nums数组中移动数据。
解法二:申请堆区空间,然后从第k个元素开始拷贝,再将剩余的元素顺序拷贝,最后再将堆区数据拷贝到nums数组。
但tnnd,解法一很容易就运行超时(因为有一些极其恶心的测试数据,会使时间效率达到O(n^2),解法二的话没啥问题,但是作为当代模范青年,我们要挑战自己的软肋!!!
解法三:三次逆置,只要我逆置的够快,题目就反应不过来,不多bb,直接开搞。。。
全局代码:
void rotate(int* nums, int numsSize, int k)
{
int i=0,j=0,tmp;
k%=numsSize;
for(i=0,j=numsSize-k-1;i<j;i++,j--)
{
tmp=nums[i];
nums[i]=nums[j];
nums[j]=tmp;
}
for(i=numsSize-k,j=numsSize-1;i<j;i++,j--)
{
tmp=nums[i];
nums[i]=nums[j];
nums[j]=tmp;
}
for(i=0,j=numsSize-1;i<j;++i,j--)
{
tmp=nums[i];
nums[i]=nums[j];
nums[j]=tmp;
}
}
以示例一为例:
(1)首先,先对轮转次数k做处理,因为有可能 k>numSize,这样就会有规律的循环,例如,如果k>numSize,轮转1次和轮转numSize+1次的结果相同,轮转numSize次与原数组相同。酱紫,就会减少不必要的操作。
(2)第一个for循环,逆置第k个数之前的数值
(3)第二个for循环,逆置后k个数值
(4)第三个for循环,整体逆置
这样就达到了题目要求,且时间复杂度仅为O(n);
三步的操作不能毫不相干,只能说一毛一样,所以完全可以去写一个函数,直接利用接口去操作,可以减少代码冗余,提高可阅读性。
void reserve(int* nums,int m,int n)
{
int i=m,j=n,tmp;
for(;i<j;i++,j--)
{
tmp=nums[i];
nums[i]=nums[j];
nums[j]=tmp;
}
}
void rotate(int* nums, int numsSize, int k)
{
k%=numsSize;
reserve(nums,0,numsSize-k-1);
reserve(nums,numsSize-k,numsSize-1);
reserve(nums,0,numsSize-1);
}
实不相瞒
我第一次看到这个解法时,表情是酱紫的 (0.0)
所以说,刷算法题,要有一个高的效率,多去学习和总结解题方法和思路,死磕一个题,可以但没有必要!!!
寄了,再见。。。