7-9 数列循环右移

题目链接

题意

将数组a中的每个元素循环向右移m个位置

思路(未实现):

定义i,j两指针,
i指向移动前坐标,j指向移动后坐标
定义变量t记录当前a[j]的数值(下一次a[i]的数值)
每次i=j;
多次循环

方法

方法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;
    }
posted @ 2021-10-09 11:10  kingwzun  阅读(225)  评论(0编辑  收藏  举报