1、题目名称
Rotate Array(循环平移数组)
2、题目地址
https://leetcode.com/problems/rotate-array/
3、题目内容
英文:Rotate an array of n elements to the right by k steps.
中文:将一个长度为n的数组,向右平移k个单位
4、解题方法1
一个比较易于理解的方法是新开辟一个与原数组等长的数组,循环考察原数组的元素,将它们放到新数组中平移后的位置上,最后再将新数组上的元素赋回原数组。
一段可以AC的Java代码:
/**
* 功能说明:LeetCode 189 - Rotate Array
* 开发人员:Tsybius2014
* 开发时间:2015年8月9日
*/
public class Solution {
/**
* 数组平移
* @param nums 数组
* @param k 平移距离
*/
public void rotate(int[] nums, int k) {
int[] tempArray = new int[nums.length];
k %= nums.length;
//平移后的结果赋值到新数组
for (int i = 0; i < nums.length; i++) {
int j = (i - k) % nums.length;
if (j < 0) {
j += nums.length;
}
tempArray[i] = nums[j];
}
//将结果赋值回原数组
for (int i = 0; i < nums.length; i++) {
nums[i] = tempArray[i];
}
}
}
这个做法的缺点就是需要申请一个与传入数组等长的数组,当传入数组长度较长时,新申请的数组长度也很大。因此可以考虑一个不新申请数组的做法。
5、解题方法2
先考虑数组nums的长度与k互质的情况。假设nums是一个长度为7的数组,k的值是3,那么只需要6次交换就可以完成数组的移位了。各位置元素交换的次序见下图:
每次交换,都把首个元素交换到它最终会出现的位置上,而每次交换后数组的首个元素,它最后会出现的位置都距上一个元素交换到的位置向右相差k(如果超过数组长度则从数组首元素重新计数)。
再考虑nums的长度不与k互质的情况,这个时候就需要求出nums的长度与k的最大公约数g,并将原数组分为g组,每组中的元素个数与k是互质的,分组进行上面的替换。
一段实现该算法的Java代码如下:
/**
* 功能说明:LeetCode 189 - Rotate Array
* 开发人员:Tsybius2014
* 开发时间:2015年8月9日
*/
public class Solution {
/**
* 数组平移
* @param nums 数组
* @param k 平移距离
*/
public void rotate(int[] nums, int k) {
if (k == nums.length) {
return;
}
if (k > nums.length) {
k %= nums.length;
}
int temp;
int loops = gcd(nums.length, k);
for (int i = 0; i < loops; i++) {
for (int j = 1; j < nums.length / loops; j++) {
temp = nums[i];
nums[i] = nums[(i + k * j) % nums.length];
nums[(i + k * j) % nums.length] = temp;
}
}
}
/**
* 辗转相除法求最大公约数
* @param a 正整数a
* @param b 正整数b
* @return 正整数a和b的最大公约数
*/
public int gcd(int a, int b) {
if (a == 0) {
return b;
}
while (b != 0) {
if (a > b) {
a = a - b;
} else {
b = b - a;
}
}
return a;
}
}
END