题目大意:
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就是从最后一个转到第一个的次数。 如上图, k=3,就将7、6、5分别转到最左边。
1.首先是自己的答案
轮流去替换:i -> (i+k)%len 这里注意:可能轮流一轮下来,并不是每个都能替换到。比如:{1,2,3,4,5,6},k=2,这里轮流替换的为{1,3,5}、{2,4,6}才结束。因此需要一个变量来记录有没有每个都轮到num++,然后每轮的开头,分别从0,1...开始,直到每个都轮到:num==len.
class Solution {
public:
void swap(int& a, int& b){
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
void rotate(vector<int>& nums, int k) {
int len = nums.size();
if(k>=len)
k = k%len;
if(k == 0)
return;
int i = 0;
int start = 0;
int temp = nums[i];
i = i+k;
int num = 0;
while(num < len){
while(i != start){
swap(nums[i],temp);
i = (i+k)%len;
num++;
}
num++;
nums[i] = temp;
start++;
i = start;
temp = nums[i];
i = (i+k)%len;
}
}
};
2.这里引入leetcode中大神总结的5种方法,其中我的方法就是他的第二种方法。
(注:以下方法是借用他人的,放在这只为自己以后能参考别人优秀代码而方便,并不是要盗取人家的知识,我在这声明,为了尊重知识产权)
1. Make an extra copy and then rotate.
Time complexity: O(n). Space complexity: O(n).
class Solution
{
public:
void rotate(int nums[], int n, int k)
{
if ((n == 0) || (k <= 0))
{
return;
}
// Make a copy of nums
vector<int> numsCopy(n);
for (int i = 0; i < n; i++)
{
numsCopy[i] = nums[i];
}
// Rotate the elements.
for (int i = 0; i < n; i++)
{
nums[(i + k)%n] = numsCopy[i];
}
}
};
2. Start from one element and keep rotating until we have rotated n different elements.
Time complexity: O(n). Space complexity: O(1).
class Solution
{
public:
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];
}
}
};
3. Reverse the first n - k elements, the last k elements, and then all the n elements.
Time complexity: O(n). Space complexity: O(1).
class Solution
{
public:
void rotate(int nums[], int n, int k)
{
k = k%n;
// Reverse the first n - k numbers.
// Index i (0 <= i < n - k) becomes n - k - i.
reverse(nums, nums + n - k);
// Reverse tha last k numbers.
// Index n - k + i (0 <= i < k) becomes n - i.
reverse(nums + n - k, nums + n);
// Reverse all the numbers.
// Index i (0 <= i < n - k) becomes n - (n - k - i) = i + k.
// Index n - k + i (0 <= i < k) becomes n - (n - i) = i.
reverse(nums, nums + n);
}
};
4. Swap the last k elements with the first k elements.
Time complexity: O(n). Space complexity: O(1).
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n = nums.size();
if (k%n == 0) return;
int first = 0, middle = n-k%n, last = n;
int next = middle;
while(first != next) {
swap (nums[first++], nums[next++]);
if (next == last) next = middle;
else if (first == middle) middle = next;
}
}
};
5. Keep swapping two subarrays.
Time complexity: O(n). Space complexity: O(1).
class Solution
{
public:
void rotate(int nums[], int n, int k)
{
if ((n == 0) || (k <= 0) || (k%n == 0))
{
return;
}
k = k%n;
// Rotation to the right by k steps is equivalent to swapping
// the two subarrays nums[0,...,n - k - 1] and nums[n - k,...,n - 1].
int start = 0;
int tmp = 0;
while (k > 0)
{
if (n - k >= k)
{
// The left subarray with size n - k is longer than
// the right subarray with size k. Exchange
// nums[n - 2*k,...,n - k - 1] with nums[n - k,...,n - 1].
for (int i = 0; i < k; i++)
{
tmp = nums[start + n - 2*k + i];
nums[start + n - 2*k + i] = nums[start + n - k + i];
nums[start + n - k + i] = tmp;
}
// nums[n - 2*k,...,n - k - 1] are in their correct positions now.
// Need to rotate the elements of nums[0,...,n - k - 1] to the right
// by k%n steps.
n = n - k;
k = k%n;
}
else
{
// The left subarray with size n - k is shorter than
// the right subarray with size k. Exchange
// nums[0,...,n - k - 1] with nums[n - k,...,2*(n - k) - 1].
for (int i = 0; i < n - k; i++)
{
tmp = nums[start + i];
nums[start + i] = nums[start + n - k + i];
nums[start + n - k + i] = tmp;
}
// nums[n - k,...,2*(n - k) - 1] are in their correct positions now.
// Need to rotate the elements of nums[n - k,...,n - 1] to the right
// by k - (n - k) steps.
tmp = n - k;
n = k;
k -= tmp;
start += tmp;
}
}
}
};