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].
Note:
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
[show hint]
Hint:
Could you do it in-place with O(1) extra space?
Related problem: Reverse Words in a String II
题目大意是将数组循环右移k位,循环右移的含义就是将数组向右移动,其最后一个数移动到数组第一个位置,倒数第二个数移动到最后一个位置。。。,这样算是完成了循环右移一位。
我的思路主要有两个:一、每次将数组的每一位向右移动一位,总共移动k次,但是这种做法会涉及到双层循环,当数组的长度比较大以及k的值比较大时,这种算法的效率低下,导致oj出现超时的现象,代码如下:
public class Solution {
public void rotate(int[] nums, int k) {
int i,j,temp;
int len = nums.length;
if(len == 0 || len == 1 || k == len)
return;
if(k > len)
k = k-len;
for(i = 0;i<k;++i) {
temp = nums[len-1];
for(j = len-1;j>0;j--) {
nums[j] = nums[j-1];
}
nums[0] = temp;
}
}
}
二、利用三次逆序的原理,先将下标为0~n-k-1之间的元素逆序,再将n-k~n-1之间的元素逆序,最后将0~n-1之间的元素逆序即可(n为数组长度)。例如数组a[] = {1,2,3,4,5,6,7},循环右移三位。第一次逆序后变为{4,3,2,1,5,6,7},第二次逆序后变为{4,3,2,1,7,6,5},第三次逆序后变为{5,6,7,1,2,3,4},正是所求的数组,代码如下:
public class Solution {
public void rotate(int[] nums, int k) {
int len = nums.length;
if(len == 1 || k == len)
return;
if(k > len)
k = k-len;
reverse(nums, 0, len-k-1);
reverse(nums, len-k, len-1);
reverse(nums, 0, len-1);
}
public void reverse(int[] nums,int start,int end) {
if(start >= end)
return;
int mid = (end + start) / 2;
int i,j,temp;
for(i = start,j = end;i <= mid;++i,--j) {
temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}