題目
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);
}