题目
暴力法
旋转 k k k次,每次将数组旋转1个元素。
C++代码
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int len = nums.size();
for(int i = 0;i < k;i++)
{
int temp = nums[len - 1];
for(int j = len - 1;j > 0;j--)
{
nums[j] = nums[j - 1];
}
nums[0] = temp;
}
}
};
复杂度分析
- 时间复杂度: O ( n ∗ k ) O(n*k) O(n∗k)。每个元素都被移动 1 步 ( O ( n ) ) (O(n)) (O(n)) k k k次 ( O ( k ) ) (O(k)) (O(k)) 。
- 空间复杂度: O ( 1 ) O(1) O(1) 。没有额外空间被使用。
下面是两种巧妙的官方题解方法。
环状替换法
直接把每一个数字放到它最后的位置,但这样的后果是遗失原来的元素。因此,需要把被替换的数字保存在变量 t e m p temp temp里面。然后,将被替换数字( t e m p temp temp)放到它正确的位置,并继续这个过程 n n n次, n n n是数组的长度。同时注意:如果 k k k大于 n n n,移动 k k k次实际上相当于移动 k % n k\%n k%n次。
下面是一个例子:
nums: [1, 2, 3, 4, 5, 6]
k: 2
C++代码
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int len = nums.size();
k = k % len;
int count = 0;
for (int start = 0; count < len; start++) {
int current = start;
int prev = nums[start];
do {
int next = (current + k) % len;
int temp = nums[next];
nums[next] = prev;
prev = temp;
current = next;
count++;
} while (start != current);
}
}
};
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n) 。只遍历了每个元素一次。
- 空间复杂度: O ( 1 ) O(1) O(1) 。使用了常数个额外空间。
反转法
当旋转数组 k k k次, k % n k\%n k%n个尾部元素会被移动到头部,剩下的元素会被向后移动。
在这个方法中,首先将所有元素反转。然后反转前 k k k个元素,再反转后面 n − k n-k n−k个元素,就能得到想要的结果。
假设 n = 7 n=7 n=7且 k = 3 k=3 k=3 。
原始数组 : 1 2 3 4 5 6 7
反转所有数字后 : 7 6 5 4 3 2 1
反转前 k 个数字后 : 5 6 7 4 3 2 1
反转后 n-k 个数字后 : 5 6 7 1 2 3 4 --> 结果
C++代码
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int len = nums.size();
k %= len;
reverse(nums, 0, len - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, len - 1);
}
void reverse(vector<int>& nums, int start, int end) {
while (start < end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
};
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n) 。
- 空间复杂度: O ( 1 ) O(1) O(1) 。
链接:https://leetcode-cn.com/problems/rotate-array/solution/xuan-zhuan-shu-zu-by-leetcode/
来源:力扣(LeetCode)