题目
浙大版《数据结构(第2版)》题目集——习题2.2 数组循环左移
本题要求实现一个对数组进行循环左移的简单函数:一个数组a中存有n(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移m(≥0)个位置,即将a中的数据由(a0a1⋯an−1)变换为(am⋯an−1a0a1⋯am−1)(最前面的m个数循环移至最后面的m个位置)。如果还需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?
输入格式:
输入第1行给出正整数n(≤100)和整数m(≥0);第2行给出n个整数,其间以空格分隔。
输出格式:
在一行中输出循环左移m位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。
输入样例:
8 3
1 2 3 4 5 6 7 8
输出样例:
4 5 6 7 8 1 2 3
一、解题思路
想要循环左移,本质上就是前m个数(当m大于n时取余,确保合理的移动数字)按顺序“后输出”,而其他数字按顺序“先输出”即可,而需要“后输出”的数字,肯定是需要临时变量存储的,故定义一个数组s[],并且大小最大就是n(当m是n的倍数时,输入的n个数字都需要存入临时数组“后输入”)。而如何找出“后输出”的序列,和“先输出”的序列呢?其实只需要在输入阶段用if-else判断即可:在for循环输入中,当i<m时(m需要对n取余,达到类似“循环”的效果,具体细节运行一下代码,换几个数据感受一下吧^_^)就把这些数字存入数组s中,其余的就是需要先移动的,直接用一个临时变量t去存储按顺序输入进来的数,然后printf输出即可。最后就是按顺序输出临时数组s中的数字(还有一个问题是要满足题目中的“序列结尾不能有多余空格”问题,我放在代码中解释了)
二、代码
#include<stdio.h>
int main(){
int n,m,i,t;
scanf("%d%d",&n,&m);
int s[n];
for(i=0;i<n;i++){
//i小于需要移动的次数,说明此次输入的数字需要循环向左移动,
//循环向左的本质就是,让这m%n个数字(由于m可能大于和为n的倍数,所以需要取余来限制)
//“待会儿输出”,那我们不妨不循环挨个移动再输出,而是先存着这几个数,
//等需要“先输出”的数字输出完了,再通过一个循环输出在后面即可
if(i<m%n)
scanf("%d",&s[i]);
else{
//else则说明需要“先输出”的数字,先简单用一个临时变量t储存,
// 但是未来满足“序列结尾不能有多余空格”,需要再判断一下是否是最后一个需要“先输出”的元素
scanf("%d",&t);
if(i+1!=n)//如果不是最后一个需要“先输出”的元素
printf("%d ",t);
else//最后一个“先输出”的元素
printf("%d",t);
}
}
for(i=0;i<m%n;i++){
//由于“先输出”的序列结尾元素是“空格”+“数字”的形式
//例如题目所给样例中,“先输出”的数字序列是:4 5 6 7 8
//所以为了满足“序列结尾不能有多余空格”,直接按:“空格”+数字即可
printf(" %d",s[i]);
}
return 0;
}
结果如图:
总结
一开始是想着简单的用类似于冒泡排序的方式去做,然后结合昨天晚上看了浙大版《数据结构》书中第一章解决有关“最大子列和”问题(也是题集的上一道题)的“[算法1.4] 在线处理”思想,尝试想想也有没有这种“在线”的方式做这道题呢,然后突发奇想(当然,没看其他题解自己做的,有许多问题还望不吝赐教^_^)想到了这题“先输出”和“后输出”的两种情况对数组循环左移的题解。