给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: [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]
示例 2:
输入: [-1,-100,3,99] 和 k = 2
输出: [3,99,-1,-100]
解释:
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]
说明:
尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
要求使用空间复杂度为 O(1) 的 原地 算法。
- 循环k次旋转法(略)
思路:一次循环旋转一次,用k次循环获取结果,时间复杂度为O(n^3) - 三次反转法
思路:将数组反转一次,再以第k个元素为边界前后分别反转一次即可得到答案
注意:用取余来防止k>nums.size()导致reverse函数内参数越界的问题
class Solution {
public:
void rotate(vector<int>& nums, int k) {
reverse(nums.begin(),nums.end());
reverse(nums.begin(),nums.begin()+k%nums.size());
reverse(nums.begin()+k%nums.size(),nums.end());
}
};
复杂度分析:
时间复杂度:reverse函数的时间复杂度为O(n)
空间复杂度:O(1)
- 直接替换法
思路:指针指向当前位置i,直接将i位置元素替换到目标位置j,指针移动至目标位置j,循环直至元素遍历
注意:可能会存在循环无法遍历的情况,比如示例2,因此在当前循环结束后需要移动指针至下一个位置
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int start;
int current;
int n = nums.size();
int count = 0;
for(int i=0; count<n; i++)
{
current = i;
int wait_to_move = nums[current];
do
{
current = (current+k)%n;
int temp = nums[current];
nums[current] = wait_to_move;
wait_to_move = temp;
count ++;
}
while(i!=current);
}
}
};
复杂度分析:
时间复杂度:一次遍历,O(n)
空间复杂度:为常量O(1)