1. 程式人生 > 其它 >7-9 數列迴圈右移

7-9 數列迴圈右移

題目連結

題意

將陣列a中的每個元素迴圈向右移m個位置

方法

方法1:翻轉法

步驟:
依次反轉[0, n - 1]、[0, m - 1]、[m, n - 1]。
三次翻轉得到的結果就是向右迴圈移動m位。
例子:
對於 [1 2 3 4 5 6]右移2位

  1. 翻轉區間[0, n - 1] -> [6 5 4 3 2 1]
  2. 翻轉區間[0, m - 1]-> [5 6 4 3 2 1]
  3. 翻轉區間[m, n - 1]-> [5 6 1 2 3 4]
    程式碼:
//反轉函式:反轉陣列a的[L,R]居間
void ReverseSeqlist(seqlist &a,int L,int R)
{
    while(L<R)
    {
        int t;
        t=a.data[L];
        a.data[L]=a.data[R];
        a.data[R]=t;
        L++;
        R--;
    }
}
//移動函式
void Move(seqlist &a,int m)
{
    m=m%a.length;
    ReverseSeqlist(a,0,a.length-1);
    ReverseSeqlist(a,0,m-1);
    ReverseSeqlist(a,m,a.length-1);
}

方法2:輸入時移動

程式碼:

    cin>>n>>m;
    m=m%n;
    for(int i=0;i<n;i++)
    {
        int pos=(i+m)%n;//注意這裡的取餘
        cin>>a[pos];
    }

方法3:輔助佇列法

普通佇列:

步驟:
只要把隊頭的元素出隊、再入隊(隊尾),重複n - m次。
例子:
對於 佇列[1 2 3 4 5 6] 移動2位。

  1. 隊頭放入隊尾 [2 3 4 5 6 1]
  2. 隊頭放入隊尾 [3 4 5 6 1 2]
  3. 隊頭放入隊尾 [4 5 6 1 2 3]
  4. 隊頭放入隊尾 [5 6 1 2 3 4]
    4次出隊、入隊操作得到的最終結果就是向右迴圈移動兩次的結果。

雙端佇列:

m次把隊尾放入隊頭

方法3:多次移動法

步驟:
暴力,每次移動一位,移動m次
程式碼:

   for(int i=0; i<m; i++)
    {
       int j=a.length-1;
       int tmp=a.data[j];
        for(int k=0;k<a.length;k++)
        {
            a.data[j-k]=a.data[j-k-1];
        }
        a.data[0]=tmp;
    }