1.1 实现一个算法,确定一个字符串的所有字符是否全部不同。假如不允许使用额外的数据结构,又该如何处理?
解决方案:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
#include <iostream>
#include <cstring> // strlen() #include <cstdio> // getchar() using namespace std; /************************************************************************/ // 函数名称:isUniqueChars_1 (使用字符数组实现) // 函数目的:判断字符串中所有字符是否全部不同 // 函数参数:str // 函数返回:true:字符全部不同 // 使用条件:字符集为ASCII /************************************************************************/ bool isUniqueChars_1( const char* str) { if (strlen(str) > 256) return false; char strFlag[ 256] = { 0}; for (size_t i = 0; i < strlen(str); i++){ int val = *(str + i); if (!strFlag[val]) strFlag[val] = 1; else return false; } return true; } /************************************************************************/ // 函数名称:isUniqueChars_2 (使用位向量实现) // 函数目的:判断字符串中所有字符是否全部不同 // 函数参数:str // 函数返回:true:字符全部不同 // 使用条件:字符集为ASCII /************************************************************************/ bool isUniqueChars_2( const char* str) { if (strlen(str) > 256) return false; char strBit[ 256/ 8 + 1] = { 0}; for (size_t i = 0; i < strlen(str); i++){ int val = *(str + i); int index = val / 8; int mod = val % 8; if ( (strBit[index] & ( 1 << mod)) > 0 ){ return false; } strBit[index] |= ( 1 << mod); } return true; } int main() { char str[] = "MyNameisJoh"; char str2[] = "MyNameisJohnnyHu"; cout << str << " is " << (isUniqueChars_1(str) ? "true" : "false") << endl; cout << str2 << " is " << (isUniqueChars_1(str2) ? "true" : "false") << endl; cout << str << " is " << (isUniqueChars_2(str) ? "true" : "false") << endl; cout << str2 << " is " << (isUniqueChars_2(str2) ? "true" : "false") << endl; getchar(); return 0; } |
思考体会:
1、 是否询问 “字符范围” ?
2、分析及计算(时间\空间)复杂度;
3、如果是Unicode字符该如果处理?
4、其他常规解法: 双for循环、排序等,他们复杂度多少
1.2 用C/C++实现void reverse(char* str)函数,即反转一个null结尾的字符串。
解决方案:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
#include <iostream>
#include <cstring> // strlen() #include <cstdio> // getchar() using namespace std; /************************************************************************/ // 函数名称:reverse // 函数目的:反转一个null结尾的字符串 // 函数参数:str // 函数返回:无 // 使用条件: /************************************************************************/ void reverse( char* str) { size_t length = strlen(str); for (size_t i = 0; i < length; i++){ if ( i < length - 1 - i ){ char ch = *(str + i); *(str + i ) = *(str + length - 1 - i); *(str + length - 1 - i) = ch; } else { return; } } return; } int main() { char str[] = "MyNameisJohnnyHu"; cout << "str = "<< str << endl; cout << "call reverse() function, The result is:" << endl; reverse(str); cout << "str = " << str << endl; getchar(); return 0; } |
运行结果:
思考体会:
1、如果不使用任何其他函数(比如:strlen)该怎么做?
2、注意对null字符的利用。
1.3 给定两个字符串,请编写程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。
解决方案:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include <iostream>
#include <string> #include <algorithm> // std::sort using namespace std; /************************************************************************/ // 函数名称:permutation // 函数目的:确定两个字符串中字符是否相同(忽略顺序) // 函数参数:s, t // 函数返回:true:字符串中字符相同; false:不相同 // 使用条件: /************************************************************************/ bool permutation( const string& s, const string& t) { string ss = s, tt = t; sort( ss.begin(), ss.end() ); sort( tt.begin(), tt.end() ); return ss == tt; } int main() { char str[] = "MyNameisJohnnyHu"; char str2[] = "NameisMyHuJohnny"; cout << "str = "<< str << endl; cout << "str2 = " << str2 << endl; cout << "call permutation() function, The result is:" << endl; cout << ( permutation(str, str2) ? "true" : "false" ) << endl; getchar(); return 0; } |
运行结果:
思考体会:
1、其他方法:可以检查两个字符串中各个字符数是否相同。字符集假设为ASCII。
2、用纯C语言去实现,使用qsort去排序。
2、最此题之前应确认一些细节。
1.4 . 编写一个方法,将字符串中的空格全部替换为“%20”。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。
示例:
输入: "Mr John Smith"
输出:Mr%20John%20Smith“
解决方案:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include <iostream>
#include <string> #include <algorithm> // std::replace using namespace std; /************************************************************************/ // 函数名称:replaceChars // 函数目的:确定两个字符串中字符是否相同(忽略顺序) // 函数参数:str字符串,s原字符子串, t要替换的字符子串 // 函数返回:true:字符串中字符相同; false:不相同 // 使用条件: /************************************************************************/ string replaceChars( const string& str, const string& s, const string& t) { string strNew = str; while (strNew.find(s) != std::string::npos){ strNew.replace(strNew.find(s),s.length(), t); } return strNew; } int main() { string str; cout << "Please enter a string: " << endl; getline(std::cin, str); cout << "call replaceChars() function, The result is:" << endl; cout << replaceChars(str, " ", "%20") << endl; getchar(); return 0; } |
运行结果:
思考体会:
1、用纯cC去怎么完成?
2、其他解法?
1.5 利用字符重复出现的次数,编写一个方法,实现基本的字符串压缩功能。比如,字符串“aabcccccaaa”会变成"a2b1c5a3"。 若“压缩”后的字符串没有变短,则返回原来的字符串。
解决方案:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
#include <iostream>
#include <sstream> // std::stringstream #include <string> #include <cstdio> // getchar() using namespace std; /************************************************************************/ // 函数名称:compressChars // 函数目的:基本字符串压缩功能 // 函数参数:str要压缩的字符串 // 函数返回:压缩操作过的字符串 // 使用条件: /************************************************************************/ string compressChars( const string& str) { if (str.size() <= 2) return str; string strPress; size_t sz = 0; char ch = str[ 0]; for (size_t i = 0; i < str.size(); i++){ if (ch == str[i]){ ch = str[i]; sz += 1; } else { stringstream ss; ss << sz; // std::to_string在MinGW下有Bug strPress += ch + ss.str(); ch = str[i]; sz = 1; } if (i == str.size() - 1){ stringstream ss; ss << sz; strPress += ch + ss.str(); } } return ( (strPress.size() < str.size()) ? strPress : str); } int main() { char str[] = "aaaaabbccdddddeeeefgg"; char str2[] = "MyNameisJohnnyHuuu"; cout << "str = "<< str << " ---->> " << compressChars(str) << endl; cout << "str2 = "<< str2 << " ---->> " << compressChars(str2) << endl; getchar(); return 0; } |
运行结果:
思考体会:
1、其他解法?
2、分析(时间/空间)复杂度
1.6 给定一幅由NxN矩阵表示的图像,其中每个像素的大小为4字节,编写一个方法,将图像旋转90度,不占用额外的内存空间能否做到?
解决方案:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
#include <iostream>
#include <sstream> // std::stringstream #include <string> #include <cstdio> // getchar() #define N 4 using namespace std; /************************************************************************/ // 函数名称:rotateMatrix // 函数目的:顺时针90度转置矩阵 // 函数参数:matrix // 函数返回:无 // 使用条件: /************************************************************************/ void rotateMatrix( int matrix[][N], int rows = N) { for (size_t layer = 0; layer < rows / 2; ++layer){ size_t first = layer; size_t last = rows - 1 -layer; for (size_t i = first; i < last; ++i){ size_t offest = i - first; // 存储上边 int top = matrix[first][i]; // 左到上 matrix[first][i] = matrix[last - offest][first]; // 下到左 matrix[last - offest][first] = matrix[last][last - offest]; // 右到下 matrix[last][last - offest] = matrix[i][last]; // 上到右 matrix[i][last] = top; } } return; } int main() { int matrix[N][N] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12}, { 13, 14, 15, 16} }; cout << "初始矩阵:" << endl; for (size_t i = 0; i < N; i++){ for (size_t j = 0; j < N; j++){ cout << matrix[i][j] << "\t"; } cout << endl; } rotateMatrix(matrix, N); cout << "顺时针转置90度后矩阵:" << endl; for (size_t i = 0; i < N; i++){ for (size_t j = 0; j < N; j++){ cout << matrix[i][j] << "\t"; } cout << endl; } getchar(); return 0; } |
运行结果:
思考体会:
1、该算法是参考的算法,算法设计很精妙,值得研究掌握。
2、本算法从外向内旋转,又如何从内向外旋转?
3、本算法的时间复杂度O(N^2),
1.7 编写一个算法,若MxN矩阵中某个元素为0,则将其所在的行与列清零。
解决方案:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
#include <iostream>
#include <sstream> // std::stringstream #include <string> #include <cstdio> // getchar() #define N 4 using namespace std; /************************************************************************/ // 函数名称:setZero // 函数目的:把矩阵中元素为0的行/列清零 // 函数参数:matrix // 函数返回:无 // 使用条件:row <= N void setZero( int matrix[][N], size_t rows = N) { int flag[N][N] = { { 0} }; for (size_t row = 0; row < rows; row++){ for (size_t col = 0; col < N; col++) if (matrix[row][col] == 0) flag[row][col] = 1; } // 行/列清零 for (size_t row = 0; row < rows; row++){ for (size_t col = 0; col < N; col++) if (flag[row][col] == 1) { for (size_t c = 0; c < N; c++) matrix[row][c] = 0; for (size_t r = 0; r < rows; r++) matrix[r][col] = 0; } } return; } int main() { int matrix[N][N] = { { 1, 2, 3, 4 }, { 5, 0, 7, 8 }, { 9, 0, 11, 12}, { 13, 14, 15, 16} }; cout << "初始矩阵:" << endl; for (size_t i = 0; i < N; i++){ for (size_t j = 0; j < N; j++){ cout << matrix[i][j] << "\t"; } cout << endl; } setZero(matrix, N); cout << "调用setZero后:" << endl; for (size_t i = 0; i < N; i++){ for (size_t j = 0; j < N; j++){ cout << matrix[i][j] << "\t"; } cout << endl; } getchar(); return 0; } |
运行结果:
思考体会:
1、注意题设的陷阱。
2、计算时间空间复杂度。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include <iostream>
#include <string> #include <cstdio> // getchar() using namespace std; /************************************************************************/ // 函数名称:isRotation_2 // 函数目的:判断字符串是否是转换字符串 // 函数参数:s1 s2 // 函数返回:true:是转置字符串 // 使用条件: /************************************************************************/ bool isRotation_2( const string& s1, const string& s2) { size_t len = s1.length(); if (len == s2.length() && len > 0){ string s1s1 = s1 + s1; // the key point size_t found = s1s1.find(s2); if ( found != std::string::npos ) return true; } return false; } int main() { char s1[] = "waterbottle"; char s2[] = "erbottlewat"; cout << "s1 = " << s1 << endl; cout << "s2 = " << s2 << endl; cout << "调用转换字符函数isRotation_2()判断之后:" << endl; cout << (isRotation_2(s1, s2) ? "true" : "false") << endl; getchar(); return 0; } |