题目
一个数组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
类似题解
https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/01.01.md
里面有一些举一反三的例子,非常适合看。
思考
这题题意很简单,然而我不会。(都不好意思的说,我第一个通过的算法是作弊了的,使用了两个数组…)
之后开始尝试暴力移位法,很明显是不符合要求的,这里就当练一下代码。另外,以后输入输出还是尽量用scanf和printf了,因为cin和cout比较耗时。
1 |
|
可能是PAT官网的oj不太好?上面的这个暴力做法也通过了。当然,也上网查了一下其他人的做法,就是我肯定想不出来的做法。看上面的那个github,似乎是一种叫做三步反转法的东东,这里就用它博客的例子来解释。
三步反转法
给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“abcdef”前面的2个字符’a’和’b’移动到字符串的尾部,使得原字符串变成字符串“cdefab”。请写一个函数完成此功能,要求对长度为n的字符串操作的时间复杂度为 O(n),空间复杂度为 O(1)。
除了暴力移位法外,可以使用三步反转法。
将一个字符串分成X和Y两个部分,在每部分字符串上定义反转操作,如X^T,即把X的所有字符反转(如,X=”abc”,那么X’=”cba”),那么就得到下面的结论:(X’Y’)’=YX,显然就解决了字符串的反转问题。
例如,字符串abcdef,若要让def翻转到abc的前头,只要按照下述3个步骤操作即可:
- 首先将原字符串分为两个部分,即X:abc,Y:def;
- 将X反转,X->X’,即得:abc->cba;将Y反转,Y->Y’,得到:def->fed;
- 反转上述步骤得到的结果字符串X’Y’,即反转字符串cbafed的两部分给予反转,得到defabc,形式化表示为(X’Y’)’=YX,这就实现了整个反转。
代码可以这么写:
1 | void ReverseString(char *s, int from, int to){ |
看手的解释!生动形象!
针对PAT的新解法
1 |
|
最后提交上去,怎么时间比暴力还长呢…看来oj确实一般般~