字符串常见算法题

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
pHashKey++; }
// if the string is empty // or every char in the string appears at least twice return 0; }
int main() {
char array[] = "abcdacd"; char p = FirstNotRepeatingChar(array); printf("the first not repeatring char: %c\n", p); return 0; }
pEnd--;
// Reverse the whole sentence Reverse(pBegin, pEnd);
// Reverse every word in the sentence pBegin = pEnd = pData; while(*pBegin != '\0') {
if(*pBegin == ' ') { pBegin ++; pEnd ++;
我们换一种思路,从里向外来判断。也就是先判断子串A是不是对称的,如果A不对称,那么向该字符串两端各延长一个字符得到的字符串 肯定不是对称的;如果A对称,那么只需要判断A两端延长的一个字符是不是相等的,如果相等,则延长后的字符串是对称的。
int GetLongestSymmetricalLength(ar *str) {
定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。 如把字符串abcdef左旋转2位得到字符串cdefab。按照字符串 反转的结论,X="ab",Y="cdef",要想把XY变成YX,只要使用YX=(XTYT)T 即可,也就是分别对X、Y进行反转,然后再整体反转一次即 可。
翻转句子中单词的顺序
记住前面我们已经把原先的第一个字符a和后面的b做了交换为了保证这次c仍然是和原先处在第一位置的a交换我们在拿c和第一个字符交换之前先要把b和a交换回来
字符串常见算法题
字符串常见算法题
左旋转字符串
在字符串上定义反转的操作XT,即把X的所有字符反转(如X="abc",那么XT="cba")。如果将一个字符串分成两部分,X和Y两个部分,那 么我们可以得到下面的结论:(XTYT)T=YX。
if (NULL == str) return 0;
char *p = str; char *last = str + strlen(str);
char *ret = (char*)malloc(sizeof(str)); memset(ret, 0, sizeof(str));
int length = 1;
字符串的排列
问题描述:
输入一个字符串,打印出该字符串中字符的所有排列。
例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab、cba。
思路:
以三个字符abc为例来分析一下求字符串排列的过程。首先我们固定第一个字符a,求后面两个字符bc的排列。当两个字符bc的排列求好之 后,我们把第一个字符a和后面的b交换,得到bac,接着我们固定第一个字符b,求后面两个字符ac的排列。现在是把c放到第一位置的时候 了。记住前面我们已经把原先的第一个字符a和后面的b做了交换,为了保证这次c仍然是和原先处在第一位置的a交换,我们在拿c和第一个 字符交换之前,先要把b和a交换回来。在交换b和a之后,再拿c和处在第一位置的a进行交换,得到cba。我们再次固定第一个字符c,求后 面两个字符b、a的排列。既然我们已经知道怎么求三个字符的排列,那么固定第一个字符之后求后面两个字符的排列,就是典型的递归思路 了。
if (startA > endA) {
if (startB > endB) { return 0;
} else { return endB - startB + 1;
} }
if (startB > endB) { if (startA > endA) { return 0;
} else { return endA - startA + 1;
} }
if (A[startA] == B[startB]) { return CalculateStringDistance(A, startA+1, endA, B, startB+1, endB);
} else { int t1 = CalculateStringDistance(A, startA+1, endA, B, startB, endB); int t2 = CalculateStringDistance(A, startA, endA, B, startB+1, endB); int t3 = CalculateStringDistance(A, startA+1, endA, B, startB+1, endB); return MIN(t1,t2,t3)+1;
hashTable[i] = 0;
// get the how many times each char appears in the string char* pHashKey = pString; while (*(pHashKey) != '\0')
hashTable[*(pHashKey++)] ++;
printf("Distance=%d\n", d);
return 0; }
第一个只出现一次的字符
问题描述:
在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。
思路:
我们可以在第一次扫描字符串的时候,把每个字符出现的次数记录到一个容器中(hash结构),然后第二次扫描的时候,再读这个容器,就 知道每个字符出现的次数。
begin--; end++; }
new_len = end - begin - 1; if (new_len > length) {
length = new_len; strncpy(ret, begin+1, length); }
p++; }
printf("got %s\n", ret); free(ret); return length; }
continue;
// A word is between with pBegin and pEnd, reverse it } else if(*pEnd == ' ' || *pEnd == '\0') {
Reverse(pBegin, --pEnd); pBegin = ++pEnd;
} else { pEnd ++;
pBegin ++, pEnd --; } }
char* ReverseSentence(char *pData) {
if(pData == NULL) return NULL;
char *pBegin = pData; char *pEnd = pData;
while(*pEnd != '\0') pEnd ++;
char FirstNotRepeatingChar(char* pString) {
if (!pString) return 0;
// get a hash table, and initialize it const int tableSize = 256; unsigned int i, hashTable[tableSize]; for (i = 0; i < tableSize; ++ i)
// find the first char which appears only once in a string pHashKey = pString; while(*pHashKey != '\0') {
if(hashTable[*pHashKey] == 1) return *pHashKey;
} }
int main() {
char str1[] = "Hello World"; char str2[] = "Hillo Worl";
int len1 = strlen(str1); int len2 = strlen(str2);
int d = CalculateStringDistance(str1, 0, len1, str2, 0, len2);
注意:这里默认输入的字符串是ASCII码,因此只需要一个256大小的数组就可以容纳所有可能出现的字符。
对称字符串的最大长度
问题描述: 输入一个字符串,输出该字符串中对称的子串的最大长度。 例如输入"google",由于该字符串里最长的对称子字符串是"goog",因此输出4.
思路:
最暴力的解法就是遍历字符串所有的子串,然后依次检查每个子串是否是对称字符串,最后得到一个最大的对称子串。
while (p < last ) {
// substrings with odd length char *begin = p - 1; char *end = p + 1;
while (begin >= str && end < last && *begin == *end) { begin--; end++;
问题描述:
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样 处理。
例如输入“I am a student.”,则输出“student. a am I”。
思路:
借鉴字符串旋转的方法,我们先颠倒句子中的所有字符。这时,不但翻转了句子中单词的顺序,而且单词内字符也被翻转了。我们再颠倒每 个单词内的字符。由于单词内的字符被翻转两次,因此顺序仍然和输入时的顺序保持一致。还是以上面的输入为例子。翻转“I am a student.”中所有字符得到“.tneduts a ma I”,再翻转每个单词中字符的顺序得到“students. a am I”,正是符合要求的输出。
其实,我们不需要关心字符串是如何变得相同的,所以,上面6个操作可以合并为: 1、一步操作之后,计算A[2:lenA]和B[1:lenB]的距离; 2、一步操作之后,计算A[1:lenA]和B[2:lenB]的距离; 3、一步操作之后,计算A[2:lenA]和B[2:lenB]的距离;
#define MIN_META(a,b) (a>b?b:a ) #define MIN(a,b,c) MIN_META(MIN_META(a,b), c) int CalculateStringDistance(char *A, int startA, int endA, char *B, int startB, int endB) {
}
int new_len = end - begin - 1; if (new_len > length) {
length = new_len; strncpy(ret, begin+1, length); }
// substrings with even length begin = p; end = p + 1; while (begin >= str && end < last && *begin == *end) {
void Reverse(char *pBegin, char *pEnd) {
if (pBegin == NULL || pEnd == NULL) return;
char temp; while (pBegin < pEnd) {
temp = *pBegin; *pBegin = *pEnd; *pEnd = temp;
} }
return pData; }
字符串的编辑距离
将两个不同的字符串变得相同,具体的操作方法为:
1、修改一个字符(如 把"a"替换为"b"); 2、增加一个字符(如 把"abdd"变为"aebdd"); 3、删除一个字符(如 把"travelling"变为"traveling");
首先,两个字符串的距离肯定不超过它们的长度之和(可以通过删除操作把两个串都转化为空串)。 如果两个字符串A和B的第一个字符相同,则问题转化为求A[2:lenA]和B[2:lenB]的编辑距离; 如果两个字符串A和B的第一个字符不同,可以作如下操作: 1、删除A[1],然后计算A[2:lenA]和B[1:lenB]的距离; 2、删除B[1],然后计算A[1:lenA]和B[2:lenB]的距离; 3、修改A[1],使之等于B[1],然后计算A[2:lenA]和B[2:lenB]的距离; 4、修改B[1],使之等于A[1],然后计算A[2:lenA]和B[2:lenB]的距离; 5、将B[1]放到A串前,然后计算A[1:lenA]和B[2:lenB]的距离; 6、将A[1]放到B串前,然后计算A[2:lenA]和B[1:lenB]的距离;
相关文档
最新文档