一個陣列A中存有N(N>0)個整數,在不允許使用另外陣列的前提下,將每個整數迴圈向右移M(M>=0)個位置,即將A中的資料由(A0 A1……AN-1)變換為(AN-M …… AN-1 A0 A1……AN-M-1)(最後M個數迴圈移至最前面的M個位置)。如果需要考慮程式移動資料的次數儘量少,要如何設計移動的方法? 輸入格式:每個輸入包含一個測試用例,第1行輸入N ( 1<=N<=100)、M(M>=0);第2行輸入N個整數,之間用空格分隔。 輸出格式:在一行中輸出迴圈右移M位以後的整數序列,之間用空格分隔,序列結尾不能有多餘空格。 輸入樣例: 6 2 1 2 3 4 5 6 輸出樣例: 5 6 1 2 3 4
1. 就簡單的暴力移動。
#include <stdio.h> #include <stdlib.h> void right_shift(int *data,int length,int offset); void print_array(int *data,int length); int main(){ int number,move; int i; int* data; scanf("%d%d",&number,&move); data = (int *)malloc(sizeof(int)*number); for ( i = 0; i < number; i ++ ){ scanf("%d",data + i); } right_shift(data,number,move % number); print_array(data,number); return 0; } void right_shift(int *data,int length,int offset){ int index = length - offset; int shift; int temp,i,fix=index; while(index < length){ temp = data[index]; shift = index; i = fix; while( i-- ){ data[shift] = data[shift - 1]; shift --; } data[shift] = temp; index ++; } } void print_array(int *data,int length){ int i; for ( i = 0; i < length - 1; i ++ ){ printf("%d ",data[i]); } printf("%d\n",data[i]); }
2. 暴力移動的程式碼優化
上述程式碼的right_shift函式的可讀性太差,我們將其拆分未兩個函式,其中一個函式每次只向右邊移動一次(right_shift_one),right_shift函式負責呼叫right_shift_one函式完成n次的移動。
#include <stdio.h> #include <stdlib.h> void right_shift_one(int *data,int length); void right_shift_one(int *data,int length,int offset); void print_array(int *data,int length); int main(){ int number,move; int i; int* data; scanf("%d%d",&number,&move); data = (int *)malloc(sizeof(int)*number); for ( i = 0; i < number; i ++ ){ scanf("%d",data + i); } right_shift(data,number,move % number); print_array(data,number); return 0; } void right_shift_one(int *data,int length){ int temp = data[length-1]; while(--length){ data[length] = data[length - 1]; } data[length] = temp; } void right_shift(int *data,int length,int offset){ while(offset--) right_shift_one(data,length); } void print_array(int *data,int length){ int i; for ( i = 0; i < length - 1; i ++ ){ printf("%d ",data[i]); } printf("%d\n",data[i]); }
3. 巧妙的交換
上述的暴力移動明顯比較費時,下邊通過三次交換就可以完成。
#include <stdio.h> #include <stdlib.h> void reverse(int *data,int start,int end); void print_array(int *data,int length); int main(){ int number,move; int i; int* data; scanf("%d%d",&number,&move); data = (int *)malloc(sizeof(int)*number); for ( i = 0; i < number; i ++ ){ scanf("%d",data + i); } move = move % number; reverse(data,0,number - move -1); reverse(data,number - move,number - 1); reverse(data,0,number - 1); print_array(data,number); return 0; } void reverse(int *data,int start,int end){ int temp; for (;start < end; start ++,end --){ temp = data[start]; data[start] = data[end]; data[end] = temp; } } void print_array(int *data,int length){ int i; for ( i = 0; i < length - 1; i ++ ){ printf("%d ",data[i]); } printf("%d\n",data[i]); }