题目: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].
Note:
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
解答:
题意是实现数组循环右移k位,这题主要是考察空间复杂度。
解法一:Copy法
最直接的方法就是开辟一个temp[n]数组,暂存nums[n]元素,方便移位赋值,但这种方法空间复杂度为O(n)。最开始,我是分[0,n-k-1]和[n-k,n-1]两部分处理,如下所示:
void rotate(int nums[], int n, int k) {
int temp[n], i;
k = k%n; // k modulo n to limit k in [0,n-1]
for(i=0; i<n; i++)
temp[i] = nums[i];
for(i=0; i<n-k; i++)
nums[i+k] = temp[i];
for(i=n-k; i<n; i++)
nums[i-n+k] = temp[i];
}
在review讨论区的解答时,发现这两部可以合并成一部分,只需要引入取模操作。优化代码如下所示:
void rotate(int nums[], int n, int k) {
if ((n == 0) || (k <= 0)) // exception handle is essential
return;
int temp[n], i;
k = k%n; // k modulo n to limit k in [0,n-1]
for(i=0; i<n; i++)
temp[i] = nums[i];
for(i=0; i<n; i++)
nums[(i+k)%k] = temp[i];
}
解法二:递推移位法
单独考虑每一次移位操作,假设a[7] = {1,2,3,4,5,6,7},k = 3。那么,a[0]要移位到a[3],即a[3] = a[0]。同时,原来的a[3]要移位到a[6],所以在进行a[0]移位前,必须用一个中间数temp暂存a[3]的值。以此类推,一直到要移位的元素下标回到最初的地方(a[0])。这种方法空间复杂度为O(1)参考的讨论区代码如下:
void rotate(int nums[], int n, int k)
{
if ((n == 0) || (k <= 0))
{
return;
}
int cntRotated = 0;
int start = 0;
int curr = 0;
int numToBeRotated = nums[0];
int tmp = 0;
// Keep rotating the elements until we have rotated n
// different elements.
while (cntRotated < n)
{
do
{
tmp = nums[(curr + k)%n];
nums[(curr+k)%n] = numToBeRotated;
numToBeRotated = tmp;
curr = (curr + k)%n;
cntRotated++;
} while (curr != start);
// Stop rotating the elements when we finish one cycle,
// i.e., we return to start.
// Move to next element to start a new cycle.
start++;
curr = start;
numToBeRotated = nums[curr];
}
}
更多解法参考链接: