首先,假設我們有一個具有6個元素的數組: 1,2,3,4,5,6
現在我們要對這個數組循環右移4次,我們很直接很夠推出它的結果是:3,4,5,6,1,2 。但是我們如何去實現這樣一個問題呢?
我覺得大家最容易想到的方法就是:
step1:保存好數組中最后一個元素的值
step2:從第一個元素到倒數第二個元素依次向右移動一個位置
step3:然后將剛保存的值放到空出來的數組第一個位置
雖然這個方法想起來很簡單,但是它的效率卻不是很高,它的時間復雜度是O(n^2)。
現在,我再介紹一種效率較高的算法,這個算法,充分利用了模數求余的特點。
這種算法的時間復雜度是O(n),比上一種算法效率有了很大的提高。
它的主要實現步驟是這樣的:(記移動次數為move)
step1:初始化時,將pre_value初始化為數組的第一個元素
step2:從某個位置A(初始時A為0)開始開始(這里的A,B......指的是數組的下標所標志的位置),將pre_value復制到臨時變量temp中,位置A加上移動的次數得到新的位置
B = A+move,
step3:保存位置B原來的數據到pre_value中,再將變量temp中的值復制到位置B中
step4:重復上述步驟step2,step3 N次(N為數組的長度),將所有的元素都更新到正確的位置后,就可以得到正確的移位后的數組。
但是在這里我們要注意到這樣一個問題,可能存在這樣的一種情況
例如:將數組1,2,3,4,5,6 利用上訴算法循環右移3次,得到的結果將是
這里我們看到這里形成了一個只有兩個元素的環,並沒有包括所有的元素,所以經過推算,我們得到這樣兩種情況下,應該作特殊處理,
情況一:移位次數是偶數
情況二:數組長度%移位次數 == 0的情況
解決的辦法就是將一次移位動作划分為多次不含上述兩種情況的移位動作,比如將一次偶數次的移位動作分解成先進行n-1次奇數次移位,再接着進行1次移位。
(注意:千萬要注意第二種情況的問題)
下面就是我實現的代碼:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 //該函數對於數組長度為偶數且移位的次數也為偶數情況不適用,對於數組長度能整除移位次數的情況也要另加考慮 5 //所以,對於偶數的情況,我們要分解成先移動count-1+1的組合 6 void BufferRightShift(int buffer[],int n,int count) 7 { 8 int i,j; 9 int temp,pre_value; 10 pre_value = buffer[0]; 11 if(count == 0) 12 return; 13 for(i=0,j=0;i<n;i++) 14 { 15 temp = pre_value; 16 pre_value = buffer[(j+count)%n]; 17 buffer[(j+count)%n] = temp; 18 j = (j+count)%n; 19 } 20 } 21 22 23 void ROR(int buffer[],int n,int count) 24 { 25 int move = count%n; 26 if((move%2 == 0)||(n%move == 0)) //存在上面分析到的兩種情況自已的處理方法 27 { 28 int k = 1; 29 int i = move; 30 while(1) 31 { 32 if(i == 1) 33 break; 34 if((i%2 == 0) || (n%i == 0)) //統計將移位次數分解成不再出現上述兩種問題的次數 35 { 36 k++; 37 i--; 38 } 39 else 40 break; 41 } 42 BufferRightShift(buffer,n,move-k); 43 for(i=1;i<=k;i++) 44 BufferRightShift(buffer,n,1); 45 46 } 47 else 48 { 49 BufferRightShift(buffer,n,move); 50 } 51 } 52 53 int main() 54 { 55 int n,count,i; 56 int *a; 57 while(scanf("%d%d",&n,&count)!=EOF) 58 { 59 a = (int*)malloc(n*sizeof(int)); 60 for(i=0;i<n;i++) 61 scanf("%d",&a[i]); 62 63 ROR(a,n,count); 64 65 for(i=0;i<n-1;i++) 66 { 67 printf("%d ",a[i]); 68 } 69 printf("%d\n",a[n-1]); 70 free((void*)a); 71 } 72 return 0; 73 74 }
運行結果: