数组循环移位
对于存有N个整数的数组,将其向左循环移动k个位置,(x0, x1,……, xn-1)变换为(xk, xk+1, …, xn-1, x0, x1, …, xk-1)
最直接的方法就是每次将首位的数放到一个临时的整型变量中,后面N-1个数一次左移,这样需要k次才能完成,而每次的复杂度是O(N),因此总共其复杂度是O(K * N)。
while(k–) // 每次完成循环左移一位 { int Temp = Arr[0]; // 将数组的第一个元素存起来 for(int i = 0; i < N – 1; i++) // 将第2个至N个元素分别左移一位 Arr[i] = Arr[i + 1]; Arr[N – 1] = Temp; // 将存起来的元素放到末尾 }
一种比较简便的方法就是利用一个类似于德摩根定律的方法,对于数组A,将它分为两截,分别为B和C,如果分别对B和C进行逆序操作,然后再对整个数组进行逆序操作,则就可达到左移k个位置的目的。
假设原数组序列为0123456,要求变换成的数组序列为4560123,即循环左移了4位。比较之后,不难看出,其中有两段的顺序是不变的:0123和456,可把这两段看成两个整体。左移K位的过程就是把数组的两部分交换一下。变换的过程通过以下步骤完成:
1. 逆序排列0123:0123456 → 3210456;
2. 逆序排列456:3210456 → 3210654;
3. 全部逆序:3210654 → 4560123。
这个过程可以被简单地证明。
并且时间复杂度为O(N)。
void Reverse(int *Arr, int Begin, int End) { while(Begin < End) // 以中心为对称点,分别交换对偶位置上的数 { int Temp = Arr[Begin]; Arr[Begin] = Arr[End]; Arr[End] = Temp; Begin++; End–; } } void Shift(int *Arr, int N, int k) { Reverse(Arr, 0, k – 1); Reverse(Arr, k, N – 1); Reverse(Arr, 0, N – 1); }
程序是在Linux上运行的