题目
给定一个整数数组 nums
,将数组中的元素向右轮转 k
个位置,其中 k
是非负数。
个人的解法是官方题解的方法二,就是环那个,但没有用数学简化。
void rotate(vector<int>& nums, int k) {
int count =0;
int n =nums.size();
if(n==1||k==0||n==k) return ;//长度为1,移动距离为0或n都不变
k=k%n;
int index=0;
int start=0;
int cur = -1,prev = nums[0];//cur表示被更新的位置,prev表示前一个位置
while(count!=n-1){
cur = nums[(index+k)%n];
nums[(index+k)%n] = prev;//先将cur更新为当前需要更新的位置,储存值,接着将值替换为prev,然后prev=cur,往右移动一次
prev =cur;
index = (index+k)%n;
count++;//最后从循环跳出的情况是,cur储存了最后一个需要移动的值
if(index==start){
start++;
index++;
cur=-1,prev=nums[index];//更新了起点后,前置的需要往右移动的数字也需要更新
}
}
nums[(index+k)%n] = cur;//处理最后一个位置,应该是cur
}
对于回到起点的情况就均自增1即可,不用管需要循环多少次,总之n个元素都要换一次。
记下写得比较快的翻转方法:
void reverse(vector<int>& nums, int start, int end) {
while (start < end) {
swap(nums[start], nums[end]);
start += 1;
end -= 1;
}
}
void rotate(vector<int>& nums, int k) {
k %= nums.size();
reverse(nums, 0, nums.size() - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.size() - 1);
}
原理是简单的,将所有元素向右移动k位,则末尾的k%n个元素就到了前端,则先整体翻转,再分别将 [ 0 , k % n − 1 ] [0,k\%n-1] [0,k%n−1]和 [ k % n , n ] [k\%n,n] [k%n,n]区间分别翻转即可。