数组元素循环右移问题
一个数组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]); }