des算法代碼:內存移動算法代碼

   對於有k個元素的數組int a[k]={.......};寫一個高效算法將數組內容循環左移m位,
   比如:int a[6]={1,2,3,4,5,6},循環左移3位後得到結果{4,5,6,1,2,3}.


   要求:
    1.不允許另外申請數組空間,但可以申請少許變量;
    2.不允許採用每次左移。


   最直觀的想法,就是從第一個元素開始,把他一步移動到最終目的位置,而該位置原有的元素的值取出,移動到它的新位置。遞歸進行這個步驟。
   首先,我們在數學上很容易理解,這是一個一一對應映射,絕不會在一個位置上出現兩次移動。所以不會出現移動的遞歸過程中途指向了已經移動過的元素。
   那麼,這個遞歸過程唯一的終止條件就是,當前移動的元素,目的位置就是移動過程的起始位置。
   如果按照元素的索引下標標示元素,0到k-1中的任意元素i,會移動到什麼位置?
   對於任意的i,它的新位置i'=((k-m) + i)%k. (注意這裏不是 (i-m)%k ,主要是因爲i-m小於零的時候,負數對k取模爲負數。所以i-m加上k使模落在0~k-1內)


   那麼,我們可以定義這個循環鏈,取整數i0,使得0=<i0<m,定義i1=((k-m) + i0)%k,i2=((k-m) + i1)%k....ix=((k-m) + ix-1)%k.當ix=i0時循環終止。此時有i0 = ix=((k-m) + ix-1)%k=.... =(x(k-m) + i0 )%k


   因爲我們知道0<i0 <m,所以有0=x(k-m)%k,也就是說,x(k-m)=yk,因爲我們是遇到第一個x(k-m)=yk就終止,顯然等號左右的值x(k-m)或yk就是k-m和k的最小公倍數。根據數論知識,我們知道,k,m,k-m這三個數有最大公約數q,使得k=aq,m=bq,k-m=cq,a,b,c三個數兩兩互質,x(k-m)=yk => xcq = yaq => xc = ya(又因爲a,c互質)進而推出x=a,y=c。也就是說,這個遞歸過程會經歷a步(x=a)。

   因爲我們知道整個過程一共a步,k=aq,那麼i到ix的序列會形成一個步長爲q的等差序列,所以我們要移動整個0到k-1的區間,應該對0到q-1的元素應用這個遞歸算法。也就是說總共需要對q=gcd(k,k-m)個循環鏈進行遞歸過程。

      該算法的時間複雜度爲O(n),空間複雜度爲O(1).

   1:  int CommonFactor(int dividend,int divisor)//求最大公約數函數
   2:  {
   3:      if(dividend<divisor)
   4:      {
   5:          int temp=dividend;
   6:          dividend=divisor;
   7:          divisor=temp;
   8:      }
   9:      int remainder=dividend%divisor;
  10:      while(remainder!=0)
  11:      {
  12:          dividend=divisor;
  13:          divisor=remainder;
  14:          remainder=dividend%divisor;
  15:      }
  16:      return divisor;
  17:  } 
  18:   
  19:  void shift1(int a[],int k,int m)//k是數組a的元素個數,m是循環左移m位
  20:  {
  21:      int i,j,n,q=CommonFactor(k,k-m);
  22:      for(n=0;n<q;n++)
  23:      {
  24:      int temp=x[n]; i=n;j=(i+m)%k;
  25:      while(j!=n)
  26:      {
  27:          x[i]=x[j];
  28:          i=j;
  29:          j=(i+m)%k;
  30:      }
  31:      x[i]=temp; 
  32:      }
  33:  } 
  34:   
  35:  同理可以分析循環右移m位的算法
  36:  void shift1(int a[],int k,int m)//k是數組a的元素個數,m是循環右移m位
  37:  {
  38:      int i,j,n,q=CommonFactor(k,m);
  39:      for(n=0;n<q;n++)
  40:      {
  41:          int temp=x[n]; i=n;j=(k+i-m)%k;
  42:          while(j!=n)
  43:          {
  44:              x[i]=x[j];
  45:              i=j;
  46:              j=(k+i-m)%k;
  47:          }
  48:          x[i]=temp; 
  49:      }
  50:  } 
  51:   


本文來自:http://www.crazycoder.cn/Arithmetic/Article31227.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章