给定一个字符串,要求将字符串前面的若干个字符移到字符串的尾部。编程
e.g. 将「abcdef」的前3个字符移到字符串尾部,原字符串变为「defabc」。函数
一看到这个问题,第一个想法应该就是将字符串中须要移动的字符一个一个移到末尾便可实现。学习
方法以下:code
定义 LeftShift 函数,将字符串的首位移到尾部。字符串
调用 m 次 LeftShift 函数,可以使字符串开头的 m 个字符移到字符串的尾部。io
代码以下:class
#include <stdio.h> int main() { void LeftShift(char* s, int n); void LeftRotateString(char* s, int n, int m); char s[] = "abcdef"; LeftRotateString(s, strlen(s), 3); printf(s); return 0; } // 将字符串的首位移到尾部。 void LeftShift(char* s, int n) { int i; char temp = s[0]; for (i = 1; i < n; i++) { s[i - 1] = s[i]; } s[n - 1] = temp; } // 调用m次LeftShift函数,可以使字符串开头的m个字符移到字符串的尾部。 void LeftRotateString(char* s, int n, int m) { while (m--) { LeftShift(s, n); } }
时间复杂度和空间复杂度:变量
针对长度为 n 的字符串来讲,假设须要移动 m 个字符到字符串尾部,则须要 m * n 次操做。同时还需设置一个变量保存第一个字符。所以时间复杂度为 O(mn),空间复杂度为 O(1)。学习笔记
解法一因为须要一个个移动字符致使时间复杂度太高,若是想下降时间复杂度的话,换个角度思考一下,既然要求将字符串前面的一段字符串原封不动地一道字符串尾部,那么是否能够将须要移动的部分和不须要移动的部分分开处理?方法
方法以下:
将原字符串分为 X 和 Y 两个部分,其中 X 为 「abc」, Y 为「def」。
将 X 全部字符反转,即获得「cba」;将 Y 全部字符也反转,即获得「fed」。
将第二步获得的结果总体反转,即字符串从「cbafed」变为「defabc」。
代码以下:
#include <stdio.h> int main() { void ReverseString(char* s, int from, int to); void LeftRotateString(char* s, int n, int m); char s[] = "abcdef"; LeftRotateString(s, strlen(s), 3); printf(s); return 0; } // 字符串反转 void ReverseString(char* s, int from, int to) { while (from < to) { char t = s[from]; s[from++] = s[to]; s[to--] = t; } } // 三步反转 void LeftRotateStringTwo(char* s, int n, int m) { // 若要向左移动大于n为,则与%n等价。 m %= n; ReverseString(s, 0, m - 1); ReverseString(s, m, n - 1); ReverseString(s, 0, n -1); }
时间复杂度和空间复杂度:
针对长度为 n 的字符串来讲,三步反转须要操做 n 次。同时还需设置一个变量保存正在反转的第一个字符。所以时间复杂度为 O(n),空间复杂度为 O(1)。
声明:本文为July的《编程之法》的学习笔记。