面试总结(三)
1.给出一个函数来输出一个字符串的所有排列
题目叙述:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。
思路:这是个递归求解的问题。递归算法有四个特性:(1)必须有可达到的终止条件,否则程序将陷入死循环;(2)子问题在规模上比原问题小;(3)子问题可通过再次递归调用求解;(4)子问题的解应能组合成整个问题的解。
对于字符串的排列问题。如果能生成n - 1个元素的全排列,就能生成n个元素的全排列。对于只有1个元素的集合,可以直接生成全排列。全排列的递归终止条件很明确,只有1个元素时。下面这个图很清楚的给出了递归的过程。
//函数功能 : 求一个字符串某个区间内字符的全排列 //函数参数 : pStr为字符串,begin和end表示区间 //返回值 : 无 void Permutation_Solution1(char *pStr, int begin, int end) { if(begin == end - 1) //只剩一个元素 { for(int i = 0; i < end; i++) //打印 cout<<pStr[i]; cout<<endl; } else { for(int k = begin; k < end; k++) { swap(pStr[k], pStr[begin]); //交换两个字符 Permutation_Solution1(pStr, begin + 1, end); swap(pStr[k],pStr[begin]); //恢复 } } } //函数功能 : 求一个字符串某个区间内字符的全排列 //函数参数 : pStr为字符串,pBegin为开始位置 //返回值 : 无 void Permutation_Solution2(char *pStr, char *pBegin) { if(*pBegin == '\0') { cout<<pStr<<endl; } else { char *pCh = pBegin; while(*pCh != '\0') { swap(*pBegin, *pCh); Permutation_Solution2(pStr, pBegin + 1); swap(*pBegin, *pCh); pCh++; } } } //提供的公共接口 void Permutation(char *pStr) { Permutation_Solution1(pStr, 0, strlen(pStr)); //Permutation_Solution2(pStr,pStr); }
2.输出一个字符串的所有组合
题目叙述:输入一个字符串,输出该字符串中字符的所有组合。举个例子,如果输入abc,它的组合有a、b、c、ab、ac、bc、abc。
思路:同样是用递归求解。可以考虑求长度为n的字符串中m个字符的组合,设为C(n,m)。原问题的解即为C(n, 1), C(n, 2),...C(n, n)的总和。对于求C(n, m),从第一个字符开始扫描,每个字符有两种情况,要么被选中,要么不被选中,如果被选中,递归求解C(n-1, m-1)。如果未被选中,递归求解C(n-1, m)。不管哪种方式,n的值都会减少,递归的终止条件n=0或m=0。
//函数功能 : 从一个字符串中选m个元素 //函数参数 : pStr为字符串, m为选的元素个数, result为选中的 //返回值 : 无 void Combination_m(char *pStr, int m, vector<char> &result) { if(pStr == NULL || (*pStr == '\0'&& m != 0)) return; if(m == 0) //递归终止条件 { for(unsigned i = 0; i < result.size(); i++) cout<<result[i]; cout<<endl; return; } //选择这个元素 result.push_back(*pStr); Combination_m(pStr + 1, m - 1, result); result.pop_back(); //不选择这个元素 Combination_m(pStr + 1, m, result); } //函数功能 : 求一个字符串的组合 //函数参数 : pStr为字符串 //返回值 : 无 void Combination(char *pStr) { if(pStr == NULL || *pStr == '\0') return; int number = strlen(pStr); for(int i = 1; i <= number; i++) { vector<char> result; Combination_m(pStr, i, result); } }
3.最长连续字符
题目叙述:用递归算法写一个函数,求字符串最长连续字符的长度,比如aaaabbcc的长度为4,aabb的长度为2,ab的长度为1。
//最长连续字符 int findlongest(char* str) { if (str==NULL) return 0; if (*str=='\0') return 1; if(*str==*(str+1)) return 1 + findlongest(str+1); return findlongest(str+1); }
4.求子数组的最大和
题目叙述:输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2, 因此输出为该子数组的和18。
//求连续子数组的最大和 int maxSum(int a[],int n) { int i; int b=0,sum=0; for (i = 0;i < n;i++) { if (b<0) { b=a[i]; } else { b+=a[i]; } if (sum<b) { sum = b; } } return sum; }
5.字符串是否包含问题
题目叙述: 假设这有一个各种字母组成的字符串A,和另外一个字符串B,字符串里B的字母数相对少一些。什么方法能最快的查出所有小字符串B里的字母在大字符串A里都有?
比如,如果是下面两个字符串: String 1: ABCDEFGHLMNOPQRS String 2: DCGSRQPO 答案是true,所有在string2里的字母string1也都有。
如果是下面两个字符串: String 1: ABCDEFGHLMNOPQRS String 2: DCGSRQPZ 答案是false,因为第二个字符串里的Z字母不在第一个字符串里。
//字符串是否包含问题 int IsContain(char* str1,char* str2) { int i,j,flag = 1; int hash[26] = {0}; int len1 = strlen(str1),len2 = strlen(str2); for (i = 0;i < len1;i++) { hash[*(str1+i)-'A'] = 1; } for (j = 0;j < len2;j++) { if (hash[*(str2+j)-'A'] == 0) { flag = 0; break; } } return flag; }