單詞翻轉(4種思路,C/C++程式碼)
輸入一個英文句子,翻轉句子中單詞的順序,要求單詞內字元的順序不變,句子中單詞以空格隔開,為簡單起見,標點符號和普通字母一樣處理。例如:輸入“I am a student.”則輸出:“student. a am I”。
思路一:最後一個單詞的位置是不用移動的。從後面往前面遍歷,遇到第一個空格時,開始統計下一個單詞的長度n,統計完成後將該單詞後面的單詞向前移動n位,並將該單詞移動到字串的末尾;依照這樣的方式,直至遍歷完整個字串。
評:該方法的實現過程異常複雜,時間複雜度太高。
思路二:從後往前依次遍歷源字串src,每次遍歷完一個單詞後,直接將該單詞整個拷貝到另一個字串dst中,依次遍歷原字串,分別將每個獨立的單詞拷貝到dst中。
評:該演算法的空間複雜度比較高,因為需要多申請一段空間dst來儲存遍歷的結果。
思路三:將整個字串翻轉,然後分別將字串中的單個單詞獨立進行翻轉。
思路四:三步反轉法:先將每個單詞分成獨立的幾部分,然後分別對它們進行翻轉,返回將整個字串進行翻轉。(最後一步的翻轉其實是可以省略的,直接將字串從後往前輸出即可)
評:思路三和四的思想是一樣的,個人更喜歡第四種。
輸入:“I am a student.”
中間結果:“I ma a .tneduts”
輸出:“student. a am I”
C/C++程式碼
//輸入“I am a student.”則輸出:“student. a am I”。 #include <stdio.h> #include <string.h> #include <iostream> #include <string.h> using namespace std; void *reverse(char *src, char *dst) { char *p1, *p2; if(src == NULL || dst == NULL) { return NULL; } //從src的最後一個字元開始遍歷 p1 = src + strlen(src) - 1; p2 = p1; while (p1 != src) { if (*p1 == ' ') { int len = p2 - p1;//單詞的長度 memcpy(dst, p1 + 1, len); //每個單詞的末尾加上一個空格 dst += len; *dst++ = ' '; p1--; p2 = p1; } else { //不斷將p1向前移動 p1--; } } //最後一次拷貝單詞 int len = p2 - p1 + 1; memcpy(dst, p1, len); dst += len; *dst++ ='\0'; } void print(char *s, int m) { for (int i = 0; i < m; i++) { if (s[i] == ' ') cout << " "; else cout << s[i]; } cout << endl; } int main() { char *dst; dst = (char*)malloc(sizeof(char) * 10); char a[] = "I am a student."; //單詞的長度 int n = strlen(a); cout << "n=" << n << endl; //顯示未翻轉前的字串 print(a, n); //單詞翻轉 reverse(a, dst); //顯示翻轉之後的字串 print(dst, n); return 0; }
//三步反轉法 #include"stdafx.h" #include<iostream> using namespace std; void print(char *s, int m) { for (int i = 0; i < m; i++) { cout << s[i]; } cout << endl; } //將每個單詞進行翻轉 void reverse(char *s,int low,int high) { while (low < high) { int tmp = s[high]; s[high] = s[low]; s[low] = tmp; low++; high--; } } int main() { int num = 0; int low, high; //cout << "請輸入一個字串:"; char a[] = "I am a student."; //單詞的長度 int n = strlen(a); cout << "n=" << n << endl; //顯示未翻轉前的字串 print(a, n); //將字串分為獨立的幾個單詞,並分別進行翻轉 for (int i = 0; i <= n; i++) { if (a[i] == ' '||a[i]=='\0') { //單詞翻轉 reverse(a,i-num,i-1); num = 0; } else { num++; } } //中間結果 print(a, n); //顯示翻轉之後的字串 for (int i = n-1; i >=0; i--) { cout << a[i]; } cout << endl; return 0; }
附:
memcpy 函式用於把資源記憶體(src所指向的記憶體區域)拷貝到目標記憶體(dest所指向的記憶體區域);拷貝多少個?有一個count變數控制拷貝的位元組數;函式原型:void *memcpy(void *dest, void *src, unsigned int count);用法:可以拷貝任何型別的物件,因為函式的引數型別是void*(未定義型別指標),也就是說傳進去的實參可以是int*,short*,char*等等;但是由於函式拷貝的過程是一個位元組一個位元組的拷貝的,所以實際操作的時候要把void*強制轉化為char*,這樣在指標加的時候才會保證每次加一個位元組。