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位
- 翻转区间[0, n - 1] -> [6 5 4 3 2 1]
- 翻转区间[0, m - 1]-> [5 6 4 3 2 1]
- 翻转区间[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位。
- 队头放入队尾 [2 3 4 5 6 1]
- 队头放入队尾 [3 4 5 6 1 2]
- 队头放入队尾 [4 5 6 1 2 3]
- 队头放入队尾 [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;
}