劍指Offer題解(三)字串問題
阿新 • • 發佈:2018-12-12
#include<vector> using namespace std; // getline(cin, str); //一行一行輸入可輸入空格 #pragma region 替換空格 字串 //請實現一個函式,將一個字串中的每個空格替換成“%20”。 //例如,當字串為We Are Happy.則經過替換之後的字串為We%20Are%20Happy。 #pragma endregion class Solution { public: void replaceSpace(char *str, int length) { int len = 0; for (int i = 0; i < length; i++) { if (str[i] != ' ') len++; else { len += 3; } } char *pStr1 = str + len; char *pStr2 = str + length; while (pStr2 != pStr1) { if (*pStr2 == ' ') { *pStr1-- = '0'; *pStr1-- = '2'; *pStr1-- = '%'; } else { *pStr1-- = *pStr2; } pStr2--; } } }; #pragma region 第一個只出現一次的字元 //在一個字串(0<=字串長度<=10000,全部由字母組成)中找到第一個只出現一次的字元,並返回它的位置, 如果沒有則返回 -1(需要區分大小寫). #pragma endregion class Solution { public: int FirstNotRepeatingChar(string str) { int hashTable[255]; for (int i = 0; i < 256; i++) { hashTable[i] = 0; } for (int i = 0; i < str.length(); i++) { hashTable[str[i]] ++; } for (int i = 0; i < str.length(); i++) { if (hashTable[str[i]] == 1) return i; } return -1; } }; #pragma region 字串的排列 字串 遞迴 全排列 //輸入一個字串, 按字典序打印出該字串中字元的所有排列。例如輸入字串abc, 則打印出由字元a, b, c所能排列出來的所有字串abc, acb, bac, bca, cab和cba。 #pragma endregion class Solution { public: vector<string> retStrings; void PermutationChar(string str, int i) { if (i == str.size() - 1) retStrings.push_back(str); else { for (int j = i; j < str.size(); j++) { if (i != j && str[i] == str[j]) continue; else { swap(str[i], str[j]); PermutationChar(str, i + 1); } } } } vector<string> Permutation(string str) { PermutationChar(str, 0); return retStrings; } }; #pragma region 正則表示式匹配 字串 遞迴 //請實現一個函式用來匹配包括'.'和'*'的正則表示式。模式中的字元'.'表示任意一個字元,而'*'表示它前面的字元可以出現任意次(包含0次)。 //在本題中,匹配是指字串的所有字元匹配整個模式。例如,字串"aaa"與模式"a.a"和"ab*ac*a"匹配,但是與"aa.a"和"ab*a"均不匹配 #pragma endregion class Solution { public: bool match(char* str, char* pattern) { if (str == nullptr || pattern == nullptr) return false; return matchCore(str, pattern); } bool matchCore(char* str, char* pattern) { if (*str == '\0' && *pattern == '\0') return true; if (*str != '\0' && *pattern == '\0') return false; if (*(pattern + 1) == '*') { if (*pattern == *str || (*pattern == '.' && *str != '\0')) return matchCore(str + 1, pattern + 2) || matchCore(str + 1, pattern) || matchCore(str, pattern + 2); else return matchCore(str, pattern + 2); } if (*str == *pattern || (*pattern == '.' && *str != '\0')) return matchCore(str + 1, pattern + 1); return false; } }; #pragma region 表示數值的字串 字串 數字 數值 //請實現一個函式用來判斷字串是否表示數值(包括整數和小數)。例如,字串"+100","5e2","-123","3.1416"和"-1E-16"都表示數值。 //但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。 #pragma endregion class Solution { public: bool isNumeric(char* string) { if (string == nullptr) return false; bool numeric = isInteger(&string); if (*string == '.') { ++string; numeric = isUnsignedInteger(&string) || numeric; } if (*string == 'e' || *string == 'E') { ++string; numeric = numeric && isInteger(&string); } return numeric && *string == '\0'; } bool isUnsignedInteger(char** str) { const char* tem = *str; bool ret = false; while (**str != '\0' && **str >= '0' && **str <= '9') { ++(*str); ret = true; } return ret; } bool isInteger(char** str) { if (**str == '+' || **str == '-') ++(*str); return isUnsignedInteger(str); } }; //牛客中不要用itoa 改用 sprintf(char*, "%d", int); #pragma region 把字串轉換成整數 atoi //將一個字串轉換成一個整數(實現Integer.valueOf(string)的功能,但是string不符合數字要求時返回0),要求不能使用字串轉換整數的庫函式。 //數值為0或者字串不是一個合法的數值則返回0。 #pragma endregion class Solution { public: int StrToInt(string str) { if (str.length() < 1) return 0; long long num = 0; bool isNegtive = false; bool isValid = true; int ret = 0; char* charStr = strdup(str.c_str()); if (*charStr == '-') { isNegtive = true; ++charStr; } else if (*charStr == '+') { ++charStr; } while (*charStr != '\0') { if (*charStr < '0' || *charStr > '9') { isValid = false; return 0; } else { ret = ret * 10 + *charStr - '0'; } ++charStr; } if (isNegtive) { ret = -ret; if (ret < INT_MIN) { isValid = false; return 0; } } else { if (ret > INT_MAX) { isValid = false; return 0; } } int retInt = (int)ret; return retInt; } }; #pragma region 字元流中第一個不重複的字元 字串 流 雜湊 //請實現一個函式用來找出字元流中第一個只出現一次的字元。例如,當從字元流中只讀出前兩個字元"go"時,第一個只出現一次的字元是"g"。 //當從該字元流中讀出前六個字元“google"時,第一個只出現一次的字元是"l"。 //如果當前字元流沒有存在出現一次的字元,返回#字元。 #pragma endregion class Solution { public: int occurence[256] = { 0 }; string str; //Insert one char from stringstream void Insert(char ch) { str += ch; ++occurence[ch]; } //return the first appearence once char in current stringstream char FirstAppearingOnce() { char ret = '#'; for (int i = 0; i < str.size(); ++i) { if (occurence[str[i]] == 1) { ret = str[i]; break; } } return ret; } }; #pragma region 左旋轉字串 字串 翻轉 反轉 //組合語言中有一種移位指令叫做迴圈左移(ROL),現在有個簡單的任務,就是用字串模擬這個指令的運算結果。 //對於一個給定的字元序列S,請你把其迴圈左移K位後的序列輸出。 //例如,字元序列S=”abcXYZdef”,要求輸出迴圈左移3位後的結果,即“XYZdefabc”。是不是很簡單?OK,搞定它! #pragma endregion class Solution { public: void ReverseString(char *str, const int &begin, const int &end) { char *charStart = str + begin; char *charEnd = str + end; while (charStart < charEnd) { char tem = *charStart; *charStart = *charEnd; *charEnd = tem; ++charStart; --charEnd; } } string LeftRotateString(string str, int n) { if (n < 0 || n > str.length() - 1) return str; //string.h //char * charStr = new char[strlen(str.c_str()) + 1]; //strcpy(charStr, str.c_str()); char* charStr = strdup(str.c_str()); ReverseString(charStr, 0, n - 1); ReverseString(charStr, n, str.length() - 1); ReverseString(charStr, 0, str.length() - 1); string ret; ret = charStr; return ret; } }; #pragma region 翻轉單詞順序列 字串 翻轉 反轉 //牛客最近來了一個新員工Fish,每天早晨總是會拿著一本英文雜誌,寫些句子在本子上。 //同事Cat對Fish寫的內容頗感興趣,有一天他向Fish借來翻看,但卻讀不懂它的意思。 //例如,“student. a am I”。後來才意識到,這傢伙原來把句子單詞的順序翻轉了,正確的句子應該是“I am a student.”。 //Cat對一一的翻轉這些單詞順序可不在行,你能幫助他麼? #pragma endregion class Solution { public: void ReverseString(char *str, const int &begin, const int &end) { char *charStart = str + begin; char *charEnd = str + end; while (charStart < charEnd) { char tem = *charStart; *charStart = *charEnd; *charEnd = tem; ++charStart; --charEnd; } } string ReverseSentence(string str) { int begin = 0; int end = 1; char* charStr = strdup(str.c_str()); while (end <= str.length()) { if (charStr[end] == ' ' || charStr[end] == '\0') { ReverseString(charStr, begin, end - 1); begin = end + 1; } ++end; } ReverseString(charStr, 0, str.length() - 1); string ret; ret = charStr; return ret; } }; #pragma region 把陣列排成最小的數 字串 陣列 排序 qsort sort //輸入一個正整數陣列,把數組裡所有數字拼接起來排成一個數,列印能拼接出的所有數字中最小的一個。 //例如輸入陣列{3,32,321},則打印出這三個數字能排成的最小數字為321323。 #pragma endregion class Solution { public: static int compare(const void* strNumber1, const void* strNumber2) { char* g_StrCombine1 = new char[10 * 2 + 1]; char* g_StrCombine2 = new char[10 * 2 + 1]; strcpy(g_StrCombine1, *(const char**)strNumber1); strcat(g_StrCombine1, *(const char**)strNumber2); strcpy(g_StrCombine2, *(const char**)strNumber2); strcat(g_StrCombine2, *(const char**)strNumber1); return strcmp(g_StrCombine1, g_StrCombine2); } string PrintMinNumber(vector<int> numbers) { string ret; if (numbers.size() < 1) return ret; char** strNumbers = (char**)malloc(sizeof(char*)* numbers.size()); for (int i = 0; i < numbers.size(); ++i) { strNumbers[i] = new char[10 + 1]; sprintf(strNumbers[i], "%d", numbers[i]); } qsort(strNumbers, numbers.size(), sizeof(char*), compare); for (int i = 0; i < numbers.size(); ++i) ret += strNumbers[i]; free(strNumbers); return ret; } }; #pragma region 全排列 九宮格 電話號碼 轉 字元組合 #pragma endregion class Solution { public: string str[8] = { "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" }; vector<string> retVector; vector<string> letterCombinations(string digits) { int len = digits.length(); if (len <= 0) return retVector; for (int i = 0; i < len; ++i) { if (digits[i] < '2' || digits[i] > '9') { return retVector; } } string a; letterCombinationsRecursive(digits, 0, len, a); return retVector; } void letterCombinationsRecursive(string &digits, int begin, const int &length, string beforeStr) { if (begin == length) { retVector.push_back(beforeStr); } for (int i = 0; i < str[digits[begin] - '2'].length(); ++i) { letterCombinationsRecursive(digits, begin + 1, length, beforeStr + str[digits[begin] - '2'][i]); } } }; int main(int argc, char* argv[]) { Solution sl; vector<string> retVector = sl.letterCombinations("23456"); }