給定一個字符串,要求將字符串前面的若干個字符移到字符串的尾部。編程
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的《編程之法》的學習筆記。