編程之美 - 數組循環移位

問題描述:
將一個數組向右循環移位 k 位,要求只使用兩個參數,時間複雜度爲 O(N)。

思路 1:
採用蛙跳的方式,用當前的元素 i,替換第i+k個元素,這樣逐一替換N次後,數組被移位完成。
當然這時要區分能兩種情況,N整除k 和 N不能整除k,這時跳的方式是不一樣的。
時間複雜度 O(N)

假設 N = 7 k = 3 (N不能整除k),  假設 N = 9 k = 3 (N能整除k)

pic_1
思路 2:
例如 1 2 3 4 5 6 7,移位3位後會變成  5 6 7 1 2 3 4。 

找規律, 發現 5 6 7是會被移動的,所以書中的想法是把數組分成兩個部分 一部分是 0 到 N-k-1,另一部分是 N - k 到 N。

第一次變化: 將數組中 0 到  N-k-1進行翻轉
第二次變化: 將數組中 N - k 到 N進行翻轉
第三次變化: 將整個數組進行翻轉

1 2 3 4 5 6 7   == 第一次變化 ==>  4 3 2 15 6 7   == 第二次變化 ==>  4 3 2 1 7 6 5  == 第三次變化  ==>  5 6 7 1 2 3 4

要遍歷兩次數組 2xN,時間複雜度 O(N)

#include <iostream>

using namespace std;

void printarr(int arr[], int len)
{
    int i = 0;
    for (i = 0 ; i < len; i++)
    {
        cout << arr[i] << "  ";
    }
    cout << endl << endl;
}

/////////////////////////////////////////////////////
//  algorithm one
/////////////////////////////////////////////////////
void swap1(int arr[], int len, int k)
{
    int i = 0, cnt=0;

    cout << "Algorithm 1: "<< "shift: " << k << endl;
    k %= len;

    if (len%k == 0)
    {
        cnt = 0;
        while(cnt < k)
        {
            for (i = cnt+k; i < len; i=i+k)
            {
                arr[cnt] = arr[cnt] ^ arr[i];
                arr[i] = arr[i] ^ arr[cnt];
                arr[cnt] = arr[cnt] ^ arr[i];
            }
            cnt++;
        }
    }
    else
    {
        while(cnt < len-1)
        {
            i = i + k;
            if (i < len)
            {
                cout << arr[0] << "<==>" << arr[i] << endl;
                arr[0] = arr[0] ^ arr[i];
                arr[i] = arr[i] ^ arr[0];
                arr[0] = arr[0] ^ arr[i];
            }
            else
            {
                i = i%len;
                cout << arr[0] << "<==>" << arr[i] << endl;
                arr[0] = arr[0] ^ arr[i];
                arr[i] = arr[i] ^ arr[0];
                arr[0] = arr[0] ^ arr[i];
            }
            cnt++;
        }
    }
    printarr(arr, len);
}

/////////////////////////////////////////////////////
//  algorithm two
/////////////////////////////////////////////////////
void reserve(int arr[], int l, int r)
{
    int tmp = 0;
    for(; l < r; l++, r--)
    {
        tmp = arr[l];
        arr[l] = arr[r];
        arr[r] = tmp;
    }
}
void swap2(int arr[], int len, int k)
{
    cout << "Algorithm 2: "<< "shift: " << k << endl;

    k %= len;
    reserve(arr, 0, len-k-1);
    reserve(arr, len-k, len-1);
    reserve(arr, 0, len-1);

    printarr(arr, len);
}

int main()
{
    int len = 0, k = 0;
    int test[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    len = sizeof(test)/sizeof(test[0]);

    int *parr = new int[len];

    k = 4;
    memcpy(parr, test, len*sizeof(int));
    cout << "----------------------------------" << endl;
    printarr(parr, len);

    swap1(parr, len, k);
    memcpy(parr, test, len*sizeof(int));
    swap2(parr, len, k);

    k = 2;
    memcpy(parr, test, len*sizeof(int));
    cout << "----------------------------------" << endl;
    printarr(parr, len);
    swap1(parr, len, k);
    memcpy(parr, test, len*sizeof(int));
    swap2(parr, len, k);

    k = 1;
    memcpy(parr, test, len*sizeof(int));
    cout << "----------------------------------" << endl;
    printarr(parr, len);
    swap1(parr, len, k);
    memcpy(parr, test, len*sizeof(int));
    swap2(parr, len, k);

    k = 3;
    memcpy(parr, test, len*sizeof(int));
    cout << "----------------------------------" << endl;
    printarr(parr, len);
    swap1(parr, len, k);
    memcpy(parr, test, len*sizeof(int));
    swap2(parr, len, k);
    delete[] parr;
    cin >> len;
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章