PAT乙级C语言1008 数组元素循环右移问题

1008 数组元素循环右移问题

一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0A​1⋯A​N−1)变换为(A​N−M⋯A​N−1A​0A​1⋯A​N−M−1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

输入格式:
每个输入包含一个测试用例,第1行输入N(1≤N≤100)和M(≥0);第2行输入N个整数,之间用空格分隔。

输出格式:
在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。

输入样例:

6 2
1 2 3 4 5 6

输出样例:

5 6 1 2 3 4
#include<stdio.h>
int main()
{
	int n;//输入n个数
	int m;//输入数向右移
	int a[100];
	
	scanf("%d%d",&n,&m);
	
	for(int i = 0 ; i < n;i++)
	{
		scanf("%d",&a[i]);
	}
	
	if(1 == n)
	{
		printf("%d",a[0]);
	}
	else if(n > m )
	{
		for(int i = n - m ; i < n;i++)
		{
			if (i == n - m)
				printf("%d",a[i]);
			else
				printf(" %d",a[i]);
		}
	
		for(int i = 0; i < n - m;i++)
			printf(" %d",a[i]);
	}
	else if(m % n == 0)
	{
		for(int i = 0;i < n;i++)
		{
			if (i == 0)
				printf("%d",a[i]);
			else
				printf(" %d",a[i]);
		}
	} 
	else
	{
		for(int i = n - m % n ; i < n;i++)
		{
			if (i == n - m % n)
				printf("%d",a[i]);
			else
				printf(" %d",a[i]);
		}
	
		for(int i = 0; i < n - m % n;i++)
			printf(" %d",a[i]);
	}
	return 0;
}

没考虑到一些特殊情况,按着牛客网的测试案例来改的,所以写的繁琐。但是牛客网的有个测试点没过去,pat的能过去,就没继续深究了。

其中取余的想法是从https://blog.csdn.net/qq_40840749/article/details/81781789 以及https://blog.csdn.net/qq_15046309/article/details/86516764 两位博主中的代码看到的。
1)不要想当然地认为N>M,所以在M>N时需要对M进行处理,即作取余计算M=M%N
2)考察的是输出格式的问题,注意一点,即移动的数值会大于原来数组的长度。因此实际的移动数是对数组的长度取余

以及这个博主的想法也可以借鉴,还没有仔细深究。
https://www.cnblogs.com/tenjl-exv/p/9783143.html
思路分析:
  对于循环移动的问题
  将移动个数所在位置左右两边分别反序,再整体反序即可
  PS:
    针对M大于N的情况,取mod(n,m)
    如果向右移动,则从右向左数M
    如果向左移动,则从左向右数M

2022-10-02更新
时隔多年又重新做了这道题。本来想着使用int a[N],输入的时候使用while(N–),结果在尝试输出数组的时候输出为空。再输出N值的时候发现输出为-1。看了眼书中的前半部分,就把数组定义为int a[110]了。这回的思路是,先校正M的值,在输入的时候就输入到它移动后的位置上,最后直接正常输出了。

#include<stdio.h>

int main(){
	int M, N;
	scanf("%d%d", &N, &M);
	int a[110]; 
	int n = M % N;
	for(int i = n; i < N; i++){
		scanf("%d", &a[i]);	
	}
	for(int i = 0; i < n; i++){
		scanf("%d", &a[i]);
	}
	for(int j = 0; j < N; j++){
		if(j != N-1){
			printf("%d ", a[j]);
		}else{
			printf("%d", a[j]);	
		}
	}
	return 0;
}

书中思路:
题目中虽然给出了很多限制,例如不允许使用另外的数组、又要考虑移动数据的次数最少,但实际上却只测试循环右移之后得到的结果而不管过程。

首先需要注意题目并没有给定M的最大值,因此不能直接认为M< N,而需要在读入N和M后令M=M%N,这样就可以保证M<N,使后面操作更简单。这样做的依据是:对一个长度为N的序列,右移N位之后的序列和当前序列是相同的。

在得到新的M后,可以直接输出序列从N-M号元素到N-1号元素,再输出0号元素到N-M-1号元素即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值