PAT 1008. 数组元素循环右移问题
2016-04-28 21:41
302 查看
题目信息:
一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0 A1……AN-1)变换为(AN-M …… AN-1 A0 A1……AN-M-1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?
输入格式:每个输入包含一个测试用例,第1行输入N ( 1<=N<=100)、M(M>=0);第2行输入N个整数,之间用空格分隔。
输出格式:在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。
输入样例:
6 2
1 2 3 4 5 6
输出样例:
5 6 1 2 3 4
分析:题目只是说明了M>=0,那么有可能M>=N。当超过整个数组的长度,实际只要向右循环M-N位就可以了。所以,首先要对循环的位数和数组长度取余数,即move=M%N。要求尽量少的移动,如果使用最直接的方法,每次循环右移动M位,需要移动M*N次。其实仔细想想有规律。一个长度为6的数组为1 2 3 4 5 6,向右移动两位,先从元素1开始,元素1要移动到元素3的位置,元素3到了元素5的位置,元素5回到起始的元素1的位置。再由元素2开始,元素2到了元素4的位置,元素4到了元素6的位置,元素6到了起始的元素2的位置。a[i+2]=a[i],当i+2超过数组长度时,对数组长度进行取余数就可以了,当i+2的位置到了起始位置,本次移动结束了。如图。
但是该如何控制数组起点呢?长度为6的话有两个起始位置,如果数组为1 2 3 4 5 6 7向右移动两位 1->3->5->7->2->4->6->1;起始位置只有一个。仔细观察发现从一次起点开始,遍历过最小的位置就是以后循环的边界,如长度为6,第一右移动为1->3->5->1最小的数为3。位置3就是边界。第二次移动的位置就是上一次加一,即位置2,小于位置3。所以还要从位置2再次进行右移。而长度为7,移动的最小位置为2,所以起始位置只有一个。
用这种方法数组长度为多少位,就移动多少位。时间复杂度O(n),比最直接的方法高效。
C语言实现:
一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0 A1……AN-1)变换为(AN-M …… AN-1 A0 A1……AN-M-1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?
输入格式:每个输入包含一个测试用例,第1行输入N ( 1<=N<=100)、M(M>=0);第2行输入N个整数,之间用空格分隔。
输出格式:在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。
输入样例:
6 2
1 2 3 4 5 6
输出样例:
5 6 1 2 3 4
分析:题目只是说明了M>=0,那么有可能M>=N。当超过整个数组的长度,实际只要向右循环M-N位就可以了。所以,首先要对循环的位数和数组长度取余数,即move=M%N。要求尽量少的移动,如果使用最直接的方法,每次循环右移动M位,需要移动M*N次。其实仔细想想有规律。一个长度为6的数组为1 2 3 4 5 6,向右移动两位,先从元素1开始,元素1要移动到元素3的位置,元素3到了元素5的位置,元素5回到起始的元素1的位置。再由元素2开始,元素2到了元素4的位置,元素4到了元素6的位置,元素6到了起始的元素2的位置。a[i+2]=a[i],当i+2超过数组长度时,对数组长度进行取余数就可以了,当i+2的位置到了起始位置,本次移动结束了。如图。
但是该如何控制数组起点呢?长度为6的话有两个起始位置,如果数组为1 2 3 4 5 6 7向右移动两位 1->3->5->7->2->4->6->1;起始位置只有一个。仔细观察发现从一次起点开始,遍历过最小的位置就是以后循环的边界,如长度为6,第一右移动为1->3->5->1最小的数为3。位置3就是边界。第二次移动的位置就是上一次加一,即位置2,小于位置3。所以还要从位置2再次进行右移。而长度为7,移动的最小位置为2,所以起始位置只有一个。
用这种方法数组长度为多少位,就移动多少位。时间复杂度O(n),比最直接的方法高效。
C语言实现:
//24K丶小烦 #include<stdio.h> #define LENGTH 100 int main() { int count=0,move=0,i=0,looper=101,data[LENGTH]; int param=0,save=0,temp=0,j=0; scanf("%d%d",&count,&move); move%=count; //处理移动 for(i=0;i<count;i++) scanf("%d",&data[i]); if(move) //移动0位不移动数组 { for(j=0;j<looper;j++) { param=j+move,save=data[j],temp; //记录起始位置 while(param!=j) //回到起始位置 { if(save!=data[param]) //相同元素不移动 { temp=data[param]; data[param]=save; save=temp; } if(param>j&&looper>param) looper=param; //超过数组长度 param=(param+move)%count; } data[j]=save; //回到当前位置 } } for(i=0;i<count;i++) { printf("%d",data[i]); if(i!=count-1) printf(" "); } return 0; }
相关文章推荐
- bloom filter
- Objective-C与js相互调用及传参数注意
- 接口电平标准
- IOS开发总结之UIButton常用属性和方法
- 软件架构的典型组成部分-资源管理
- 使用kernel编译+busybox定制Linux系统--实现ssh远程登录+web服务的迷你主机
- Angular学习记录-显示与隐藏
- 数据结构与算法(一) 交换
- 《常见算法和数据结构》优先队列(3)——堆排序
- 字符相关算法
- ubuntu 下安装x264库
- For循环语句的使用和函数的调用
- 二叉树的创建及其基础操作
- NOIP200505谁拿了最多的奖学金
- 第十周 技术博客发表 数据结构
- 二维数组作为形参
- R语言︱逻辑运算
- ns 2.35 安装 TKN 802.11e
- 盲打
- 第十周 周记