字符串左右旋转问题

来源:互联网 发布:ubuntu怎么看软件位置 编辑:程序博客网 时间:2024/05/15 09:56

首先说明下所谓"字符串左右旋转"是指什么:

如字符串"abcdefg"左旋2位,结果应该是"cdefgab";再对"cdefgab"右旋2位,结果应该是"abcdefg",即:

左旋n位:字符串的前n位由首部移到尾部,右旋n位:字符串的后n位由尾部移到首部。n < strlen(字符串)


1、直观的常规方法:

直观方法就是依次移位,比如abcdefg,需要左旋2位,那么先把a移位到尾部使字符串变成bcdefga,然后再把b移位到尾部是字符串变成cdefgab。

每个字符的一次直接移位的时间复杂度是O(N),如果需要移位n个字符,那么时间复杂度就是O(n * strlen(字符串))


2、O(N)的方法:

采取"先交换最后移位"的方式,依然以abcdefg左旋2位为例,先连续进行2次"交换",依次变为cdabefg、cdefabg,这时候长度已经不能再交换了,就对最后的abg进行移位变为gab,最终结果就是cdefgab。交换、移位的时间复杂度都是O(N),所以整个操作的时间复杂度也是O(strlen(字符串)):

完整程序含测试程序如下:

#include <iostream>#include <stdlib.h>//p[0: num-1]与p[num: num * 2 - 1]交换数据(O(N))void swap (char *p, int num) {for (int i = 0; i < num; i++) {char tmp = p[i];p[i] = p[i + num];p[i + num] = tmp;}}//abcde变为eabcd(O(N))void leftshift (char *p, int num) {char rightest = p[num];for (int i = num; i > 0; i--) {p[i] = p[i - 1];}p[0] = rightest;}//abcde变为bcdea(O(N))void rightshift (char *p, int num) {char leftest = p[0];for (int i = 0; i < num; i++) {p[i] = p[i + 1];}p[num] = leftest;}//还能整块交换的时候就整块交换, 不能交换的时候就移位. rotate和shift的时间复杂度都是O(N), 所以整个操作也是O(N)的时间复杂度void leftrotate (char *p, const char *q, int num) {//当前指针离字符串末尾如果不足两倍交换的长度, 就该移位了. 否则继续整块交换if (q - p >= (num * 2)) {swap(p, num);p = p + num;leftrotate(p, q, num);} else {for (int i = 0; i < num; i++) {rightshift(p, q - p);}return;}}void rightrotate (char *p, const char *q, int num) {if (p - q >= (num * 2)) {swap(p - num * 2 + 1, num);p = p - num;rightrotate(p, q, num);} else {for (int i = 0; i < num; i++) {leftshift(p - (p - q), p - q);}}}int main (int argc, char *argv[]) {char *raw = argv[1];char *res = new char(strlen(raw) + 1);memcpy(res, raw, strlen(raw));res[strlen(raw)] = '\0';std::cout << res << std::endl;int num = atoi(argv[2]);leftrotate(res, (const char *)&res[strlen(res) - 1], num);std::cout << res << std::endl;rightrotate(&res[strlen(res) - 1], (const char *)res, num);std::cout << res << std::endl;delete res;return 0;}


0 0
原创粉丝点击