题目链接:189. Rotate Array
Rotate an array of n elements to the right by k steps.
For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
Hints:
Could you do it in-place with O(1) extra space?
这道题目最简单的思路一定是brute-force方法, O(n) 时间, O(n) 空间。既过程中使用另一个数组来存储旋转结果。代码如下:
public void rotate(int[] nums, int k){
/*
brute force
*/
int[] tmp = new int[nums.length];
for (int i = 0; i < nums.length; i ++){
if (i + k < nums.length){
tmp[i + k] = nums[i];
}
else {
int j = i + k - nums.length;
while (j >= nums.length){
j -= nums.length;
}
tmp[j] = nums[i];
}
}
for (int i = 0; i < nums.length; i ++){
nums[i] = tmp[i];
}
}
考虑到我们需要至少访问每个元素一次,所以不论如何,此题的算法都至少需要
O(n)
时间。所以我们只能对空间复杂度进行优化。也就是需要考虑如何rotate-in-place,既只使用O(1)空间。方法有两种:分别如下所示。这两种方法的时间复杂度和空间复杂度均分别为
O(n)
和
O(1)
。
注意当k>n时向后旋转k位和向后旋转k%n位的效果是一样的。
- 这种方法循环将后k个元素放到正确的位置。然后再处理剩余的n-k个元素。代码如下:
public void rotate(int[] nums, int k){
/*iteratice method
first put the last k in the correct position and then deal with the remaining n-k elements.
*/
int n = nums.length;
int j = 0;
k = k % n;
while (k % n != 0 && n > 0){
for (int i = 0; i < k; i ++){
int tmp = nums[j + i];
nums[j + i] = nums[nums.length - k + i];
nums[nums.length - k + i] = tmp;
}
j += k;
n -= k;
k = k % n;
}
}
- 这种方法先旋转后k个元素,然后再旋转前n-k个元素,最后旋转整个数组。代码如下:
public void rotate(int[] nums, int k) {
/*
classic 3 way array rotate
reverse the first n-k elements
reverse the last k elements
reverse the entire array
*/
k = k % nums.length;
reverse(nums, 0, nums.length - k - 1);
reverse(nums, nums.length - k, nums.length - 1);
reverse(nums, 0, nums.length -1);
}
public void reverse(int[] nums, int start, int end){
while (start < end){
int tmp = nums[start];
nums[start++] = nums[end];
nums[end--] = tmp;
}
}