面试总结(二)
1.对称子字符串的最大长度
题目叙述:
输入一个字符串,输出该字符串中对称的子字符串的最大长度。比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4。
提示:可能很多人都写过判断一个字符串是不是对称的函数,这个题目可以看成是该函数的加强版。
第一种方法:此方法比较容易想到,但是时间复杂度比较高O(n^3)。
//判断字符串是否对称 int IsDuiChen(char *pstart,char* pend) { int flag = 1; while (pstart < pend) { if (*pstart!=*pend) { flag = 0; break; } pstart++; pend--; } return flag; } //对称字符串的最大长度 此算法时间复杂度为O(n^3) int MaxLenOfDuiChen(char *str) { int i,j = 0,MaxLen = 1; int len = strlen(str); for (i = 0;i < len;i++) { for (j = i+1;j < len;j++) { if (IsDuiChen((str+i),(str+j))== 1) { if (MaxLen < j-i+1) { MaxLen = j-i+1; } } } } return MaxLen; }
第二种方法:此方法稍微复杂,但是时间复杂度较低O(n^2)。
//对称字符串的最大长度 此算法时间复杂度为O(n^2) int LongestOfDuiChen(char* str) { int len = strlen(str),maxLen = 1; int newLen; int i=0; char* left = NULL,*right = NULL; char* pchar = str; if (str == NULL) { return; } while (i<len-1) { //子字符串为奇数 left = pchar-1; right = pchar+1; newLen = 1; while (left>=str && right<=str+len-1 && *left==*right) { left--; right++; newLen+=2; } if (newLen>maxLen) { maxLen = newLen; } //子字符串为偶数 left = pchar; right = pchar+1; newLen = 0; while (left>=str && right<=str+len-1 && *left==*right) { left--; right++; newLen+=2; } if (newLen>maxLen) { maxLen = newLen; } pchar++; i++; } return maxLen; }
2.编程判断俩个链表是否相交
题目叙述:
给出俩个单向链表的头指针,比如h1,h2,判断这俩个链表是否相交。为了简化问题,我们假设俩个链表均不带环。
问题扩展:
- 如果链表可能有环列?
- 如果需要求出俩个链表相交的第一个节点列?
无环的情况下:只需分别求出两个链表的最后一个节点判断是否相等就可以了。
//编程判断俩个链表是否相交(无环) int IsCommonOfLinklists(Node* node1,Node* node2) { int IsCommon = 0; Node* p1= node1,*p2 = node2; if (p1 == NULL || p2 == NULL) { IsCommon =0; } while (p1->next !=NULL) { p1 = p1->next; } while (p2->next !=NULL) { p2 = p2->next; } if (p1 == p2) IsCommon = 1; return IsCommon; }
可能有环的情况下:如果有环返回链表环的第一个节点。然后将得到的节点指针作为参数传入另一个链表去判断是否在其上
/编程判断俩个链表是否相交(可能有环) //如果有环返回环的第一个节点 Node* FindFirstCircleNode(Node* Head) { int flag = 0; Node *slow = Head,*fast = Head; if (Head != NULL) { return NULL; } while (fast!=NULL &&fast->next !=NULL) { slow = slow->next; fast = fast->next->next; if (slow == fast) { flag = 1; break; } } if (flag == 1) slow = Head; else return NULL; while(fast != slow) { slow = slow->next; fast = fast->next; } return fast; }
3.在O(1)时间内删除单链表结点
题目叙述:给定单链表的一个结点的指针,同时该结点不是尾结点,此外没有指向其它任何结点的指针,请在O(1)时间内删除该结点。
此题摘自<微软面试100题>中
//在O(1)时间内删除单链表结点 void DeleteNode(Node* node) { Node *Tem ,*p = node; if (node == NULL) { return; } Tem = node->next; p->c = Tem->c; p->next = Tem->next; free(Tem); Tem = NULL; }
4.字符个数的统计
题目叙述:
char *str = "AbcABca"; 写出一个函数,查找出每个字符的个数,区分大小写,要求时间复杂度是n(提示用ASCII码)
//字符个数的统计 void statisticsNumsOfChar(char* str) { int i,j,len = strlen(str); int a[256] = {0}; for (i = 0;i < len;i++) { a[*(str+i)] ++; } for (j = 0;j < 256;j++) { if(a[j] > 0) { printf("%-2c%d\n",(char)j,a[j]); } } }
5.字符串通配符匹配问题
题目叙述:在一篇英文文章中查找指定的人名,人名使用二十六个英文字母(可以是大写或小写)、空格以及两个通配符组成(*、?),通配符“*”表示零个或多个任意字母,通配符“?”表示一个任意字母。
如:“J* Smi??” 可以匹配“John Smith” .
请用C语言实现如下函数: void scan(const char* pszText, const char* pszName); 注:pszText为整个文章字符,pszName为要求匹配的英文名。 请完成些函数实现输出所有匹配的英文名,除了printf外,不能用第三方的库函数等。
该算法摘自:微软、Google等公司的面试题及解答、第161-170题
//字符串匹配问题 int scan(const char* text, const char* pattern) { const char *p = pattern; // 记录初始位置,以便patten匹配一半失败可返回原位 if (*pattern == 0) return 1; // 匹配成功条件 if (*text == 0) return 0; // 匹配失败条件 if (*pattern != '*' && *pattern != '?') { if (*text != *pattern) //如果匹配不成功 return scan(text+1, pattern); //text++,寻找下一个匹配 } if (*pattern == '?') { if (!((*text>='a' && *text<='z')||(*text>='A' && *text<='Z'))) // 通配符'?'匹配失败 { pattern = p; // 还原pattern初始位置 return scan(text+1, pattern); //text++,寻找下一个匹配 } else // 通配符'?'匹配成功 { return scan(text+1, pattern + 1); //双双后移,++ } } return scan(text, pattern+1); // 能走到这里,一定是在匹配通配符'*'了 }