189 旋转数组
题目理解
给定k和数组nums,数组元素循环右移k。
思路
①扩展数组,将长度n->2n,则右移后的数组元素为n+k,需要注意的是k可能大于n,考虑元素右移n后,位置并不会发生变化,因此实际右移后的位置为k%n。这样,右移结束后,只需把下标为n及以后的元素移到数组前即可。
② ①的方法增加了额外的空间,为减少空间复杂度,考虑直接在原数组中进行右移。假设当前为i位置,右移后的位置为i+k,显然直接将nums[i]的值赋给nums[i+k],会影响nums[i+k]的右移,因此需要考虑把当前右移的数存在一个temp中,将右移后的位置的值与temp进行交换,继续右移,如图所示。怎样判断是否结束呢,当右移后的位置为起始右移位置后,再右移就成了死循环,显然为结束条件。怎样判断所有元素都右移结束,我采用的方法是用一个count统计数值交换的次数,count=n,则所有元素都已右移。
③题解中还有一种思路是将数组右移k后,数组中尾部k个元素会移动到数组头部,因此可以先将数组全部翻转,然后再分为两部分,分别将原先尾部的k个元素和原先头部的n-k个元素翻转。
代码
①
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n=nums.size();
if(k>=n)
k=k%n;
for(int i=n-1;i>=0;i--) //要倒着来,否则数组元素可能会改变。
{
nums.resize(2*n);
nums[i+k]=nums[i];
}
for(int i=0;i<k;i++)
{
nums[i]=nums[n+i];
}
nums.resize(n);
}
};
②
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n=nums.size();
int count=0;
k=k%n;
for(int i=0;count!=n;i++)
{
int cur=i;
int temp=nums[cur];
do{
int next=(cur+k)%n;
swap(nums[next],temp);
cur=next;
count++;
}while(cur!=i);
}
}
};
③
class Solution {
public:
void rotate(vector<int>& nums,