第一次:
每次都向右平移一个,重复k次,结果超出时间限制
第二次:
想到了将k模sz(sz是数组长度)处理,然后循环替代前一个对应位置的元素,但是没有考虑到sz是k的倍数而导致一次循环并不能遍历所有元素这件事,提交运行错误
查看题解
法一是在另一新的数组中对应位置放置元素,虽然简单,确实我自己没有想到的。
法二,在原数组循环更新元素。也就是我的大体思路,官方解释数学推导挺复杂,但是在我自己的运行出错的基础上搞懂了大体含义
若从位置零开始,依次循环中2,4,6元素总是不会被访问到
这种情况总是sz是k的倍数,应该循环访问,每次循环的初始位置加一,直到初始位置为sz和k的最大公约数;
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n = nums.size();
k = k % n;
int count = gcd(k, n);//求最小公约数
for (int start = 0; start < count; ++start) {
int current = start;
int prev = nums[start];
do {
int next = (current + k) % n;
swap(nums[next], prev);//交换元素
current = next;
} while (start != current);
}
}
};
法三:三次数组翻转
k模sz处理后,向右平移k次即将尾部k个元素转移到数组首部,其余元素后移
评论中有个引用了美服的一个解释
nums = “----->–>”; k =3
result = “–>----->”;
reverse “----->–>” we can get “<–<-----”
reverse “<–” we can get “–><-----”
reverse “<-----” we can get “–>----->”
很形象
class Solution {
public:
void reverse(vector<int>&nums,int n1,int n2){
while(n1<n2){
swap(nums[n1],nums[n2]);
++n1;
--n2;
}
}
void rotate(vector<int>& nums, int k) {
k=k%(nums.size());
reverse(nums,0,nums.size()-1);
reverse(nums,0,k-1);
reverse(nums,k,nums.size()-1);
}
};