PAT 1008 数组元素循环右移问题

探讨在不使用额外数组的情况下,如何高效地将数组中的整数循环向右移动M个位置,介绍三种方法并详细解析利用三次逆置实现的最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A​0​​A​1​​⋯A​N−1​​)变换为(A​N−M​​⋯A​N−1​​A​0​​A​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

题目分析:单从结果来看,很容易想到的是,只需要实际输出的时候按题目所要求的那样输出,不去实际改变序列的顺序,就能通过,这是投机的方法。其次,如果没有时间,空间复杂度的要求,那另外开辟一个空间,然后按照想要的顺序移进去也可以,但是题目中希望考虑 。最后不知道各位能不能想到数据结构,大概是在线性表的逆置那块,遇到过类似的操作,稍加改动就可以实现这个题目。(另外,提一句,考研真题中出现过和此题几乎一样的题,不过要求是左移p个位置。思想一定要掌握,真题中难度稍大一点,但核心一样)。

方法小结:①printf输出的时候投机,按似乎右移的结果输出;

                ②不考虑空间复杂度的时候,开辟一个新的数组,按照结果依次移进去;

                ③利用数据结构中链表逆置的思想。

下面主要介绍第三种方法:假设数组num[n],需要右移m位,需要实现三次逆置,设逆置函数为:

void reverse(int num[],int left,int right,int k){
	int temp;
	for(int i=left,j=right;i<left+k&&i<j;i++,--j){ //
		temp = num[i];
		num[i] = num[j];
		num[j] = temp;
	}
}
  1. reverse(num,0,m-1,m);
  2. reverse(num,m,n-1,n-m);
  3. reverse(num,0,n-1,n);

第一次,将m之前的元素全都逆置,第二次,将m之后的元素逆置,第三次将表内所有元素全都逆置。

注意: 

题目中输入的M,只是说将整组数字右移M位,并不是说以num[m]这个数字开始,向右移动M位,这一点很重要,因为一开始我下意识的这样认为,导致结果错误。其实我们必须先找到那个第一个向右移的元素打头,当作m,然后用上三次逆置就能解决问题。

真正的m应该是n-m;

#include<iostream>
#include<vector> 
using namespace std;
void reverse(int num[],int left,int right,int k){
	int temp;
	for(int i=left,j=right;i<left+k&&i<j;i++,--j){
		temp = num[i];
		num[i] = num[j];
		num[j] = temp;
	}
}
int main()
{
	int n,m;
	cin >> n >>m;
	int num[n];
	for(int i=0;i<n;++i)
	{
		cin >> num[i];
	}
	m=m%n;       //题目中给的m是有可能大于n的;少了这一步,将会扣6分;
	m = n-m;	//找到m;
	reverse(num,0,m-1,m);
	reverse(num,m,n-1,n-m);
	reverse(num,0,n-1,n);	
	for(int i=0;i<n-1;i++){
		cout<<num[i]<<" ";
	}
	cout << num[n-1];
	return 0;
 } 

小结:

此类问题都可以用方法三得到解决,关键点在于m的位置,找到正确的m位置,然后三次逆置,就能得到正确结果。可以试一下左移是如何实现的。(左移的m就是给出的m,更简单一点。)

补充

关于reverse函数,为什么写的复杂,可以有更简单版本,如reverse(int num[],int left,int right);也使用于本题,文章提供的reverse函数,多出来的参数k含义是到第k个元素为止,看如下例题:

 有的时候我们会遇到的情况是:需要你移动的元素是前k个,和数组后端的k个顺序或者逆序交换,此时会用到参数k,但是其实这类题的实现思想和本题是类似的,只不过限制条件有变化。例题的难度高于PAT的难度,所以加以改造,例题的函数完全可以解决问题。

再补充一下一道考研数据结构的真题:

这都属于同一类型的题,思想的核心大同小异,考研里面,不属于难题的一类,需要完全透彻的理解掌握。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值