这个题有很多种解法:(n为数组长度,k为偏移步数,注意偏移值是任意值,即也要考虑负值)
1. 开辟另一个数组进行存储; Time = n(2R + 2W) [ 连续 ] Memory = n
下面是in-place rotation,即Memory = 1:
1. Time = n(R + W) [ 不连续 ]
使用gcd
如果G为n,k的gcd,那么只需进行G次循环,每次循环完成(g+k)%n,(g+2k)%n,,,(g+(n/G)*k)%n的赋值,其中g为0~G-1。这里只需要证明:各次循环之间都是没有重复的,即(g1+p*k)%n != (g2 + q*k)%n,其中g1 != g2或者p != q。可以用反证法。
Pr.
(g1+p1*k)%n != (g2 + p2*k)%n , with g1 g2 in [0, G-1], p1 p2 in [1, n/G]
if (g1+p1*k)%n == (g2 + p2*k)%n 0
{
asume :
g1 + p1*k = x1*n + c 1
g2 + p2*k = x2*n + c 2
then :
g1 - g2 + (p1 - p2)*k = (x1 - x2)*n 3
we have :
Mk = k/G Mn = n/G
then :
g1 - g2 = G*((x1 - x2)*Mn - (p1 - p2)*Mk) 4
since ((x1 - x2)*Mn - (p1 - p2)*Mk) is INTEGER, but g1 - g2 is in [1-G, G-1]
so the 4 is satisfed only when g1 - g2 = 0,
which means :
(x1 - x2)*Mn - (p1 - p2)*Mk = 0 5
since Mn and Mk are relatively prime, but x1 - x2 is in [1 - Mk, Mk - 1], and p1 - p2 is in [1 - Mn, Mn - 1]
so the 5 is satisfed only when x1 - x2 = 0 && p1 - p2 = 0
so 0 is satisfied only when g1 = g2 && p1 = p2
}
2 .Time = n(R + W) [ 不连续 ]
这个方法是基于方法2的改进,不需要计算gcd:
通过判断start = now(现在需要去赋值的nums元素),退出一次cycle
通过统计赋值次数,判断是否都完成了
3 . Time = n(2R + 2W) [ 连续 ]
三次反转数组,第一次反转 0~(n-k-1), 第二次反转(n-k) ~ n - 1, 最后在一起反转
Time = n(2R + 2W) [ 连续 ]
通过将后k个数据与前k个数据进行swap,然后待rotation数据为n-k个。k的大小在n-k < k时需要取模计算。Time = n(2R + 2W) [ 连续 ]
与方法4类似,只不过,在n-k < k时,按n-k为单位对数据进行rotation,并更新待rotation数据个数
代码如下:
class Solution {
public:
//2 read and 2 wirte each
void rotate_1(vector<int>& nums, int k) {
int size = nums.size();
if(k < 0)
k = ((k - (k/size)*size) + size);
k %= size;
if(k == 0)
return ;
vector<int> nums1(size);
for(int i=0; i<size; i++)
nums1[(i+k)%size] = nums[i];
for(int i=0; i<size; i++)
nums[i] = nums1[i];
}
//2 read and 2 wirte each
void rotate_reduceModCal(vector<int>& nums, int k) {
int size = nums.size();
if(k < 0)
k = ((k - (k/size)*size) + size);
k %= size;
if(k == 0)
return ;
vector<int> nums1(size);
int i=0, j=0;
for(; i+k<size; i++)
nums1[i+k] = nums[i];
for(; i<size; i++, j++)
nums1[j] = nums[i];
for(i=0; i<size; i++)
nums[i] = nums1[i];
}
int gcd(int a, int b)
{
int x = a%b;
if(x == 0)
return b;
return gcd(b, x);
}
//1 read 1 write each
void rotate_gcd(vector<int>& nums, int k) {
int size = nums.size();
if(k < 0)
k = ((k - (k/size)*size) + size);
k %= size;
if(k == 0)
return ;
int n=0;
int g = gcd(size, k);
for(int i=0; i<g; i++)
{
int cache=nums[i], src_id=i;
for(int j=0; j<size/g; j++)
{
int dst_id = (src_id + k) % size;
int temp_cache = nums[dst_id];
nums[dst_id] = cache;
cache = temp_cache;
src_id = dst_id;
}
}
}
//1 read 1 write each
//most fast if the size of dataType is big
void rotate_likeGcd(vector<int>& nums, int k) {
int size = nums.size();
if(k < 0)
k = ((k - (k/size)*size) + size);
k %= size;
if(k == 0)
return ;
int count = 0;
for(int s=0; count<size; s++)
{
int t = s + k;
int cache = nums[s];
while(t != s)
{
int tempData = nums[t];
nums[t] = cache;
cache = tempData;
t += k;
t = t>=size ? t - size : t;
count ++;
}
nums[s] = cache;
count ++;
}
}
void reverse(vector<int> & nums, int f, int t){
while(f < t)
{
int temp = nums[f];
nums[f] = nums[t];
nums[t] = temp;
f++;
t--;
}
}
//fast because of the memory access locality
void rotate_reverse(vector<int>& nums, int k) {
int size = nums.size();
if(k < 0)
k = ((k - (k/size)*size) + size);
k %= size;
if(k == 0)
return ;
reverse(nums, 0, size - k - 1);
reverse(nums, size - k, size - 1);
reverse(nums, 0, size -1);
}
void swap(int & a, int & b){
int temp = a;
a = b;
b = temp;
}
void rotate_swap0(vector<int>& nums, int k) {
int size = nums.size();
if(k < 0)
k = ((k - (k/size)*size) + size);
k %= size;
if(k == 0)
return ;
int n = size;
int start = 0;
while(k != 0)
{
for(int i=0; i<k; i++)
swap(nums[start+i], nums[start+n-k+i]);
n -= k;
start += k;
if(n != 0)
k = k%n;
else
break;
}
}
void rotate_swap1(vector<int>& nums, int k) {
int size = nums.size();
if(k < 0)
k = ((k - (k/size)*size) + size);
k %= size;
if(k == 0)
return ;
int n = size;
int start = 0;
while(n > k && k > 0)
{
if(n - k >= k){
for(int i=0; i<k; i++)
swap(nums[start+i], nums[start+n-k+i]);
start += k;
n -= k;
}else{
int temp = n-k;
for(int i=0; i<temp; i++)
swap(nums[start+i], nums[start+i+temp]);
start += temp;
n -= temp;
k -= temp;
}
}
}
void rotate(vector<int>& nums, int k) {
int size = nums.size();
if(k < 0)
k = ((k - (k/size)*size) + size);
k %= size;
if(k == 0)
return ;
int count = 0;
for(int s=0; count<size; s++)
{
int t = s + k;
int cache = nums[s];
while(t != s)
{
int tempData = nums[t];
nums[t] = cache;
cache = tempData;
t += k;
t = t>=size ? t - size : t;
count ++;
}
nums[s] = cache;
count ++;
}
}
};