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