【PAT B1008】数组元素循环右移问题

在这里插入图片描述

解题思路:
方法一:如上例,可先输出5,6也就是原数组的最后两位,再输出原数组的前四位,也就是1,2,3,4.或者在输入的时候就算出它在右移后的数组中的位置,直接存到对应位置即可。这个方法很简单,略。
方法二:通过转置函数reverse来实现,即先把数组的后M%N位转置,再将数组的钱N-M%N位转置,最后再将整个数组转置一次即可达到目的。
方法三:对循环节的每一元素进行移动,所谓循环节比如上例中,1要放到3的位置,3要放到5的位置,5要放到1的位置,也就是从1经一圈后又回到1,这称一个循环节。此题中,最多有M个循环节,但也有可能只有一个,所以我们要有一个变量对已归位的元素进行计数,方便终止循环。下面代码按照方法三书写。

代码示例:

#include <cstdio>
using namespace std;

int main(){
	//输入存储及预处理
	//包括右移间隔大于数组长时的处理
    int num, stride;
    int arr[110];
    scanf("%d%d", &num, &stride);
    for(int i = 0; i < num; i++)
        scanf("%d", &arr[i]);
    stride = stride % num;

	//每轮处理一个循环节(右移的循环)
	//一共最多有stride轮,如果一轮下来,不能遍历所有元素,就要新一轮
	int cnt = 0;//用于计数有多少个元素到达了正确的位置
    for(int round = 0; round < stride && cnt < num; round++){
        int i = round; //i用于在循环节中移动
		//first存储循环节的第一个元素
		//tmp用于暂存循环节中i的下一个位置的元素
		//origin暂存tmp因为每一次循环会先修改tmp
        int first = arr[round], tmp, origin = first;
        int next = (i + stride) % num;
		//当下一个位置就是循环节的第一个位置时
        while(next != round){
            tmp = arr[next];//暂存下一位置元素
			arr[next] = origin;//修改下一个位置元素为当前位置的原始值
			origin = tmp;//暂存tmp,即下一个位置的原始值
            i = next;
            next = (i + stride) % num;
        	cnt++;
		}
        arr[next] = origin;//修改循环节的第一个元素,因循环未包括
		cnt++;
    }
	//输出的最后一个数后面不能有空格
    for(int i = 0; i < num - 1; i++)
        printf("%d ", arr[i]);
    printf("%d\n", arr[num-1]);
    return 0;
}
发布了30 篇原创文章 · 获赞 1 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/lvmy3/article/details/103854003