编程之美 - 数组循环移位

问题描述:
将一个数组向右循环移位 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;
}


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