百度2012年校招笔试题——pszStringRotate
来源:互联网 发布:淘宝美食推荐 编辑:程序博客网 时间:2024/05/19 18:14
百度2013校园招聘笔试题 算法与程序设计 第4题:
字符串左移,void *pszStringRotate(char *pszString, int nCharsRotate),比如ABCDEFG,移3位变DEFGABC,要求空间复杂度O(1),时间复杂度O(n)。
字符串位移,再简单不过了,方法也很多. 有朴素算法(逐位移动,移动nCharsRotate轮)时间复杂度O(n^2),或者另开一等长新串,计算好原串中各个字符偏移之后在新串中的映射位置,时间复杂度O(n),空间复杂度O(n)。而题目要求空间复杂度O(1),时间复杂度O(n),就必须开辟新思路,想想时空复杂度更优的新算法了。
我的算法思路如下:
1.设下标索引cnt为当前在原串操作的下标位置,初始为0。
2.进行strlen(pszString)-1轮操作(i表示当前是第几次操作):
1.判断cnt和cnt循环左移i*nCharsRotate个长度位置是否是同一位置,若是,跳转至3。
2.交换cnt位置和cnt循环左移i*nCharsRotate个长度位置上的字符。
3.cnt循环右移一个长度,跳转至2。
手工模拟一个例子:ABCDEFG,左移3位
初始:ABCDEFG ,cnt = 0
交换A和(cnt+7-3%7)%7位置的字符E,得:EBCDAFG
此时cnt依然等于0,但左移长度变为2*3 = 6
交换E和(cnt+7-6%7)%7位置的字符B,得:BECDAFG
同理,第3步,B与F交换,得FECDABG
第4步,F与C交换,得CEFDABG
第5步,C与G交换,得GEFDABC
第6步,G与D交换,得DEFGABC
算法完成,得到目标串:DEFGABC
但此例比较特殊,由于(偏移长度%串长度)和串长度互素,所以任意两个交换的位置不会相等,所以cnt得不到更新,一直为0,下面看一个一般的例子:ABCDEFGH,左移4位
初始:ABCDEFGH,cnt = 0
交换A和(cnt+8-4%8)%8位置的字符E,得:EBCDAFGH
进行第2轮操作,发现cnt和(cnt+8-8%8)%8相等,故cnt循环右移,变为1.
交换B(cnt位置)和(cnt+8-12%8)%8位置的字符F,得:EFCDABGH
同理,第4步,C与G交换,得:EFGDABCH
第5步,位置相同,cnt循环右移
第6步,D与H交换,得:EFGHABCD
第7步,位置相同,cnt循环右移
算法完成,得到目标串:EFGHABCD
C++实现代码如下:
算法正确性简单证明:
第1次操作,cnt位置上的字符需要循环左移nCharsRotate个长度以达到正确位置,如果这两个位置是相等的,说明cnt位置上的字符不需要操作了,循环右移cnt(由于从0开始,可以保证其不重复)。如果这两个位置不相等,交换这两个位置的字符,此时cnt位置上的字符是新字符,这个新字符被相对循环右移了nCharsRotate个长度,而要使其达到正确位置,则需要循环左移2*nCharsRotate个长度。可以归纳出第i轮操作需要循环左移i*nCharsRotate个长度。操作完第strlen(pszString)-1轮操作即可终止,因为此轮操作只有两种可能:1.与自身交换,则最后一个字符也与自身交换,不需要额外操作;2.与最后一个字符交换,则最后一个字符在此轮操作已经被移动到了正确的位置,不需要额外操作。综上,不需要第strlen(pszString)次操作。
算法应该还可以进一步优化,比如先判断是否互素,再进行对应操作,终止轮数也相应减少,会少一些无谓的判断,现在的strlen(pszString)-1轮只是上界,真正的交换次数与上述两个量的最大公约数有关。
此外,本题还有利用串翻转性质的高效算法,本人才疏学浅,就不再详述了。
字符串左移,void *pszStringRotate(char *pszString, int nCharsRotate),比如ABCDEFG,移3位变DEFGABC,要求空间复杂度O(1),时间复杂度O(n)。
字符串位移,再简单不过了,方法也很多. 有朴素算法(逐位移动,移动nCharsRotate轮)时间复杂度O(n^2),或者另开一等长新串,计算好原串中各个字符偏移之后在新串中的映射位置,时间复杂度O(n),空间复杂度O(n)。而题目要求空间复杂度O(1),时间复杂度O(n),就必须开辟新思路,想想时空复杂度更优的新算法了。
我的算法思路如下:
1.设下标索引cnt为当前在原串操作的下标位置,初始为0。
2.进行strlen(pszString)-1轮操作(i表示当前是第几次操作):
1.判断cnt和cnt循环左移i*nCharsRotate个长度位置是否是同一位置,若是,跳转至3。
2.交换cnt位置和cnt循环左移i*nCharsRotate个长度位置上的字符。
3.cnt循环右移一个长度,跳转至2。
手工模拟一个例子:ABCDEFG,左移3位
初始:ABCDEFG ,cnt = 0
交换A和(cnt+7-3%7)%7位置的字符E,得:EBCDAFG
此时cnt依然等于0,但左移长度变为2*3 = 6
交换E和(cnt+7-6%7)%7位置的字符B,得:BECDAFG
同理,第3步,B与F交换,得FECDABG
第4步,F与C交换,得CEFDABG
第5步,C与G交换,得GEFDABC
第6步,G与D交换,得DEFGABC
算法完成,得到目标串:DEFGABC
但此例比较特殊,由于(偏移长度%串长度)和串长度互素,所以任意两个交换的位置不会相等,所以cnt得不到更新,一直为0,下面看一个一般的例子:ABCDEFGH,左移4位
初始:ABCDEFGH,cnt = 0
交换A和(cnt+8-4%8)%8位置的字符E,得:EBCDAFGH
进行第2轮操作,发现cnt和(cnt+8-8%8)%8相等,故cnt循环右移,变为1.
交换B(cnt位置)和(cnt+8-12%8)%8位置的字符F,得:EFCDABGH
同理,第4步,C与G交换,得:EFGDABCH
第5步,位置相同,cnt循环右移
第6步,D与H交换,得:EFGHABCD
第7步,位置相同,cnt循环右移
算法完成,得到目标串:EFGHABCD
C++实现代码如下:
#include <cstdio>#include <cstring>using namespace std;char str[1010];int n;void swap(char *c1, char *c2) { char tmp = *c1; *c1 = *c2; *c2 = tmp;}void pszStringRotate(char *pszString, int nCharsRotate) { int len = strlen(pszString); int cnt = 0; // Current operate position on pszString int shift = nCharsRotate % len; // Current shift length for (int i = 1; i <= len - 1; i ++) { // Operation times upper bound : len - 1 if (cnt == (cnt + len - shift) % len) { // Collision found cnt ++; // Update current operate position cnt %= len; } swap(&pszString[cnt], &pszString[(cnt + len - shift) % len]); // Do operate shift += nCharsRotate; // Update shift length shift %= len; }}int main () { while (~scanf("%s%d", str, &n)) { pszStringRotate(str, n); printf("%s\n", str); } return 0;}
算法正确性简单证明:
第1次操作,cnt位置上的字符需要循环左移nCharsRotate个长度以达到正确位置,如果这两个位置是相等的,说明cnt位置上的字符不需要操作了,循环右移cnt(由于从0开始,可以保证其不重复)。如果这两个位置不相等,交换这两个位置的字符,此时cnt位置上的字符是新字符,这个新字符被相对循环右移了nCharsRotate个长度,而要使其达到正确位置,则需要循环左移2*nCharsRotate个长度。可以归纳出第i轮操作需要循环左移i*nCharsRotate个长度。操作完第strlen(pszString)-1轮操作即可终止,因为此轮操作只有两种可能:1.与自身交换,则最后一个字符也与自身交换,不需要额外操作;2.与最后一个字符交换,则最后一个字符在此轮操作已经被移动到了正确的位置,不需要额外操作。综上,不需要第strlen(pszString)次操作。
算法应该还可以进一步优化,比如先判断是否互素,再进行对应操作,终止轮数也相应减少,会少一些无谓的判断,现在的strlen(pszString)-1轮只是上界,真正的交换次数与上述两个量的最大公约数有关。
此外,本题还有利用串翻转性质的高效算法,本人才疏学浅,就不再详述了。
- 百度2012年校招笔试题——pszStringRotate
- 百度2012笔试题
- 笔试题——2014百度校园招聘笔试题
- 笔试题86. 百度笔试题——成语接龙
- 百度笔试题——单词接龙
- 2012百度实习生笔试题
- 百度2012实习生笔试题
- 百度2013笔试题——软件研发类
- 百度笔试题——开发测试工程师(深圳)
- 百度笔试题——首相的密道
- 程序员笔试题--2012百度实习生笔试题
- 笔试题87.百度笔试题——页面调度算法
- 百度2015年校招笔试
- 百度2012实习生校园招聘笔试题
- 2012年百度实习生笔试题
- 百度2012前端实习生笔试题
- 百度2012笔试题中的原地归并
- 百度2012实习生校园招聘笔试题
- inverse和cascade
- Java源码之ArrayList(二)
- Linux中的UDP通信
- Cocos2D泰然教程推荐学习步骤
- TCP IP详解 (3)网际协议
- 百度2012年校招笔试题——pszStringRotate
- CLOCK_MONOTONIC and CLOCK_REALTIME
- Java HashMap实现详解
- struts2 中的fremark和el表达式不同之处 浅析
- Android学习笔记01
- 【ngnix】ngnix源代码分析
- QinQ
- 堆 和 栈 的 区 别 ( 经 典 )
- java 建造者模式