数组循环移位

来源:互联网 发布:知轻重明得失的意思 编辑:程序博客网 时间:2024/04/30 14:48

问题描述:

对于一个含有n个元素的数组a,将它的所有元素向后移动k位。


解决方案:

1最笨最直接的方法,就是把数组移动k次,每一次都把数组的所有元素向后移动一位,时间复杂度为O(k*n)。具体代码如下:
void First_kind(int a[],int n,int k){k%=n;while(k--)///////////////移动k次,每次都将所有元素向后移动一位。{int t=a[n-1];for(int i=n-1;i>0;i--)a[i]=a[i-1];a[0]=t;}}


2、可以用空间换时间的思想对方法1进行优化,即另外开辟一个一样大的数组b,把a移位复制到b,再逐个把元素赋值到a。时间复杂度为O(n)。具体代码如下:
void Second_kind(int a[],int n,int k){int b[256];for(int i=0;i<n;i++)b[i]=a[(i-k+n)%n];/////////////////////将数组a的元素移位后赋给bfor(i=0;i<n;i++)a[i]=b[i];}


3、对方法1进行更进一步的优化,我们可以只移动一次,将每个元素一次向后移动k位,时间复杂度为O(n)。
例如a={1,2,3,4,5,6,7,8},n=8,要向后移k=3位。则先令t=a[0],然后a[0]=a[(0-3+8)%8]=a[4],a[4]=[(4-                3+8)%8]=a[1],,,即a[i]=a[(i-k+n)%n]。
注意:当k=4时,t=a[0],a[0]=a[4],a[4]=t。此时如果还是i=(i-k+n)%n的话将产生重复移位。此时应该令i=j+1(j为      移位的起始位置)开始继续移位,即t=a[1],a[1]=a[5],a[5]=t。。。。。
具体代码如下:
void Third_kind(int a[],int n,int k){int i,j,t,m;////////////////////////////t用来存放起始的元素值,j用来存放起始的位置,m用来记录移动的元素数,当m==n时表示移动完成。k%=n;for(m=i=j=0,t=a[i];m<n;m++){if((i-k+n)%n==j)///////////////////如果i的下一个结点是j,但j元素已经移动过了的,值在t里面,则令a[i]=t,i从j+1的位置继续移动。{a[i]=t;i=++j;t=a[i];continue;}a[i]=a[(i-k+n)%n];i=(i-k+n)%n;}}


4、这种方法算是通过取巧的方法,比较少人会想到。时间复杂度也是O(n)。
例如a={1,2,3,4,5,6,7,8},n=8,要向后移k=3位。我们可以按如下步骤移:
   a、将数组分成两段,"1,2,3,4,5" 和 "6,7,8"
   b、把这两段分别逆序,则a数组变成"5,4,3,2,1,8,7,6"
   c、把数组a整段逆序,则a变成了"6,7,8,1,2,3,4,5",这不就是我们要的答案了吗!
具体代码如下:
void Change(int *a,int i,int j)//////////////////////////函数Change实现数组a从i元素到j元素逆序。{for(;i<j;i++,j--){int t=a[i];a[i]=a[j];a[j]=t;}}void Fourth_kind(int *a,int n,int k){Change(a,0,n-k-1);Change(a,n-k,n-1);Change(a,0,n-1);}



转载请注明出处,谢谢!(原文链接:http://blog.csdn.net/bone_ace/article/details/41173393)

0 0
原创粉丝点击