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.
Hint:
Could you do it in-place with O(1) extra space?
Could you do it in-place with O(1) extra space?
解法一:利用额外的空间
class Solution {
public:
void rotate(vector
& nums, int k) {
int i;
int n=nums.size();
vector
tmp=nums;
k=k%n;
for(i=0;i
时间复杂度:O(n) 空间复杂度:O(n)
解法二:通过循环替换
Using Cyclic Replacements
我们可以直接把数组中的每个数都放在旋转过后应在的位置,但这样会破化原有的元素。因此,我们需要把被替换的元素放在临时变量中,然后把临时变量放在它应该在的位置,重复进行n次,其中,n是数组的长度。因为我们要替换数组
中的所有元素,因此我们设置替换总次数为n.但是我们也会遇到一个问题,如果某次替换后,f(k)=k,k是大于n的数。这时,尽管我们可以选择一个数把它放到正确的位置,但是替换后最终回到了起点。这时候,我们就要重新选一个起点元素的下标,再开始同样的过程。
下面我们证明上述方法是如何工作的:假设这里有一个数组,其中有n个元素,要求要移动k步。初始时,所有元素都在原始位置,第一次循环后,我们替换了是k倍数的位置的元素,当再次回到初始下标时,我们已经把n/k个元素放到了正确位置。然后,把初始下标的index++,进行第二次循环,又有另外的n/k个元素被放到了正确的位置。这样的循环重复k次之后,最终由k*(n/k)=n个元素放到了正确的位置。例如:
nums: [1, 2, 3, 4, 5, 6] k: 2
class Solution {
public:
void rotate(vector
& nums, int k) {
int n=nums.size();
k=k%n;
int start;
int count=0;
for(start=0;count
时间复杂度:O(n) 空间复杂度:O(1)
解法三:通过反转 Using Reverse
一个数组移动k次后,数组后面的k个元素将反转到数组的首部,下面的算法是:先将数组整体进行反转,然后再将数组的前k个元素进行反转,再将数组的后面n-k个元素进行反转,也就得到了最后的结果。
例子:Let n=7 and k=3.
Original List : 1 2 3 4 5 6 7
After reversing all numbers : 7 6 5 4 3 2 1
After reversing first k numbers : 5 6 7 4 3 2 1
After revering last n-k numbers : 5 6 7 1 2 3 4 --> Result
class Solution {
void reverse(vector
& nums, int start, int end)
{
int n=nums.size();
while(start
& nums, int k) {
int n=nums.size();
k=k%n;
reverse(nums,0,n-1);
reverse(nums,0,k-1);
reverse(nums,k,n-1);
}
};
时间复杂度:O(n) 空间复杂度:O(1)