問題:
一個數組A中存有N(N>0)個數, 在不允許使用任何另外數組的前提下, 將每個整數循環右移M(M>0)位, 考慮移動數據的次數盡量少, 要如何設計移動方法?
並分析時間復雜度.
示意圖如下:
分析1
當然, 最簡單的方法莫過於直接每次向右移動一個, 要移動M位, 就移動M次. 代碼如下:
//傳入操作數組和移動的位數 void moveRight(int Arr[], int M) { //保存下數組的最后一個數 int endNum = Arr[N-1]; //將0~N-2位數向后移動一位 int i; for(i=N-1; i>0; i--){ Arr[i] = Arr[i-1]; } //將最后一位數放在第一位 Arr[0] = endNum; }
時間復雜度:
每移動一位就需要做N次賦值操作, 如果移動M位,則需要做NM次賦值操作
分析2
我們先將數組分成兩部分, 設后面M位為數組b, 前面N-M位為數組a, 那么怎么數組的組成就是ab.
原始數組是ab, 我的目的是將這個數組變成ba
第一步:將整個長度為N的數組倒置得到 b-1a-1 .
第二步:將 b-1 數組和 a-1 數組分別倒置, 得到 ba數組.
ab -(倒置整個長度為N的數組)-> b-1a-1 -(分別倒置兩個數組)-> ba
//該函數實現將兩個變量互換 void Swap(int *a, int *b) { //得到中間變量 *a = *a ^ *b; //b變量獲取到a的值 *b = *b ^ *a; //a變量通過中間變量獲取到當時b的值 *a = *a ^ *b; }
void moveRight(int Arr[], int N, int M) { int i, j; //轉置所有的元素 for(i=N-1, j=0; j<i; i--, j++) Swap(&Arr[i], &Arr[j]); //轉置前面M個數據 for(i=M-1, j=0; j<i; i--, j++) Swap(&Arr[i], &Arr[j]); //轉置后面面N-M個數據 for(i=N-1, j=N-M-1; j<i; i--, j++) Swap(&Arr[i], &Arr[j]); }