题目
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?
Related problem: Reverse Words in a String II
Credits:
Special thanks to @Freezen for adding this problem and creating all test cases.
分析
最简单的方法就是每次整体向右移动一个位置,但是实在是太慢了。
观察可发现其实每个元素的最终目的位置是可以算出来的(因为唯一确定),公式(index_new = (index + k)%n)所以理论上每个元素只需要移动一次。
题目要求只用 O(1)的extra space,也就不能重开一个数组了,虽然那样子非常直观而且快。
我的实现是从第一个元素开始移动,基本是三步,见代码注释。
注意到每个元素必须移动也只移动一次,所以当移动次数达到n的时候,循环要终止。
C语言代码
#include <stdio.h>
#include <QDebug>
void printNums(int nums[], int n)
{
for (int index = 0; index < n; ++index)
{
printf("%d ", nums[index]);
}
printf("\n");
}
void rotate(int nums[], int n, int k)
{
//all elements should be adjusted once and only once
//so we should stop if count == n
int count = 0;
for (int i = 0; i <n ; ++i)
{
int index = i;
int tmp = nums[index];
while(1)
{
count++;
// we are dealing with index
// it will be moved to index_new
int index_new = (index + k) % n;
// let store nums[index_new] since it will be covered
nums[i] = nums[index_new];
// move completed
nums[index_new] = tmp;
// information for the next element
tmp = nums[i];
index = index_new;
printNums(nums,n);
// if we have done a circle, break
if (i == index)
{
break;
}
}
if (count == n)
{
break;
}
}
}
int main()
{
int nums[] = {1,2,3,4,5,6,7,8,9};
int n = 9;
int k = 8;
rotate(nums, n, k);
printNums(nums, n);
}