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.
Could you do it in-place with O(1) extra space?
联想到在一个数组中插入一个数时的算法:假设插入位置为index=p,从index=len开始到index=p+1,nums[i]=num[i-1],然后nums[p]=欲插入值。
那么把一个数组从倒数第k个位置旋转,也可以用类似的办法,随便选一个元素,比如index=len-1位置的来吧,首先用temp记录下这个位置的值,把它的前k位移到这里来,而前k位的位置由前2k位置移过来,这样循环移动一边,边界出去了需要补上len,i原来ndex=len-1位置的值需要移到什么位置可以计算出来,把temp往里面填上即可。
但是一个数组比如长度为6,k=2,{1,2,3,4,5,6},那么这样移来移去也只能移元素2、4、6的位置,所以要看长度和k的关系,
具体来说,取决于GCD(len,k),比如gcd=3,那么需要3个开始位置做上面的操作,而这三个位置可以任意取,只要相邻就可以,因为是周期的。
public class Solution {
public static void rotate(int[] nums, int k)
{
int len = nums.length;
if (k >= len)
k %= len;
if(k==0)
return ;
int times=gcd(len, k);
for(int m=0;m<times;m++)
{
int temp = nums[len - 1-m];
int finishindex = (len - 1-m + k) % len;
for (int i = len - 1-m;; i -= k)
{
if (i < 0)
i += len;
if (i == finishindex)
break;
nums[i] = i - k >= 0 ? nums[i - k] : nums[i - k + len];
}
nums[finishindex] = temp;
}
}
public static int gcd(int m, int n)
{
int r=0;
while (true)
{
r = m % n;
m = n;
n = r;
if(r==0)
break;
}
return m;
}
}
public void rotate(int[] nums, int k) {
k %= nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
}
public void reverse(int[] nums, int start, int end) {
while (start < end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
本文介绍了一种在O(1)额外空间内将数组元素向右旋转k步的算法,并提供了具体的Java实现代码。通过分析数组长度与旋转步数的关系,利用最大公约数确定循环次数,实现数组的有效旋转。
373

被折叠的 条评论
为什么被折叠?



