array rotation

这个题有很多种解法:(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, 最后在一起反转

  1. Time = n(2R + 2W) [ 连续 ]
    通过将后k个数据与前k个数据进行swap,然后待rotation数据为n-k个。k的大小在n-k < k时需要取模计算。

  2. 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 ++;
        }
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章