博客主页:Skylar Lin
望本文能够给您带来一定的帮助,如果有错误的地方敬请斧正!
新人博主🧑,希望多多支持🍺,还有好多库存和大家分享🎁。
转载需注明出处和原作🌹。
轮转数组
给定一个整数数组 nums
,将数组中的元素向右轮转 k
个位置,其中 k
是非负数。
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
我的思路
-
先将 nums 数组后 k 位放入 temp 数组中;
-
再将 nums 数组移动 k 位;
-
最后将 temp 数组中前 k 位的值赋给 nums 数组。
注意:要考虑 k 大于数组长度的情况,即可通过
k = k % n;
解决。
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n = nums.size();
// 应对 k 大于数组长度的情况
k = k % n;
// 先将nums数组后 k 位放入temp数组中
vector<int> temp(k);
for(int i = 0; i < k; i++){
temp[i] = nums[n-k+i];
}
// 再将nums数组移动 k 位
for(int i = n - 1; i >= k; --i){
nums[i] = nums[i-k];
}
// 最后将temp数组中前 k 位的值赋给nums数组
for(int i = 0; i < k; i++){
nums[i] = temp[i];
}
}
};
官方题解
- 使用额外的数组
将原数组下标为 iii 的元素放至新数组下标为 (i+k) % n
的位置,最后将新数组拷贝至原数组即可。
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n = nums.size();
vector<int> newArr(n);
for (int i = 0; i < n; ++i) {
newArr[(i + k) % n] = nums[i];
}
nums = newArr;
}
};
- 环状替换(原地算法yyds)
-
从起始位置
start
开始,最初令temp=nums[start]
。根据规则,起始位置的元素会放至(start + k) % n
的位置。 -
令目标位置
pos = start;
,再令pos = (pos + k) % n;
,此时交换nums[pos]
和temp
。 -
继续更新目标位置
pos = (pos + k) % n;
,并交换temp
和nums[pos]
,重复上述过程,直至回到起始位置 。 -
如果一次循环不能遍历所有元素的话,则从下一位置开始
start++
,以此类推,直到遍历全部元素。
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n = nums.size();
k = k % n;
// 用 cnt 记录遍历的元素个数,当 cnt == n 时,则跳出循环
int cnt = 0;
for(int start = 0; start < n; start++){
int temp = nums[start];
int pos = start;
// 完成目标位置 pos 的更新,直到回到起始位置 start
do{
pos = (pos + k) % n;
swap(nums[pos], temp);
cnt++;
}while(pos != start);
if(cnt == n) break;
}
}
};