我没有记错的话是一道MSN的笔试题,网上无意中看到的,拿来做了一下。题目是这样的,给定一个字符串,一个这个字符串的子串,将第一个字符串反转,但保留子串的顺序不变。例如: 输入: 第一个字符串: "This is zhuxinquan's Chinese site: http://www.zhuxinquan.com/cn" 子串: "zhuxinquan" 输出: "nc/moc.zhuxinquan.www//:ptth :etis esenihC s'zhuxinquan si sihT" 一般的方法是先扫描一边第一个字符串,然后用stack把它反转,同时记录下子串出现的位置。然后再扫描一遍把记录下来的子串再用stack反转。我用的方法是用一遍扫描数组的方法。扫描中如果发现子串,就将子串倒过来压入堆栈。 最后再将堆栈里的字符弹出,这样子串又恢复了原来的顺序。源代码如下:
#include <iostream> #include <cassert> #include <stack> using namespace std; //reverse the string 's1' except the substring 'token'. const char* reverse(const char* s1, const char* token) { assert(s1 && token); stack<char> stack1; const char* ptoken = token, *head = s1, *rear = s1; while (*head != '/0') { while(*head!= '/0' && *ptoken == *head) { ptoken++; head++; } if(*ptoken == '/0')//contain the token { const char* p; for(p=head-1;p>=rear;p--) stack1.push(*p); ptoken = token; rear = head; } else { stack1.push(*rear); head=++rear; ptoken = token; } } char * return_v = new char[strlen(s1)+1]; int i=0; while(!stack1.empty()) { return_v[i++] = stack1.top(); stack1.pop(); } return_v[i]='/0'; return return_v; } int main(int argc, char* argv[]) { cout<<"This is zhuxinquan's Chinese site: http://www.zhuxinquan.com/cn/n"; cout<<reverse("This is zhuxinquan's Chinese site: http://www.zhuxinquan.com/cn","zhuxinquan"); return 0; }3.如何判断一棵二叉树是否是平衡二叉树
问题:判断一个二叉排序树是否是平衡二叉树 这里是二叉排序树的定义 解决方案: 根据平衡二叉树的定义,如果任意节点的左右子树的深度相差不超过1,那这棵树就是平衡二叉树。 首先编写一个计算二叉树深度的函数,利用递归实现。
template<typename T> static int Depth(BSTreeNode<T>* pbs) { if (pbs==NULL) return 0; else { int ld = Depth(pbs->left); int rd = Depth(pbs->right); return 1 + (ld >rd ? ld : rd); } }下面是利用递归判断左右子树的深度是否相差1来判断是否是平衡二叉树的函数:
template<typename T> static bool isBalance(BSTreeNode<T>* pbs) { if (pbs==NULL) return true; int dis = Depth(pbs->left) - Depth(pbs->right); if (dis>1 || dis<-1 ) return false; else return isBalance(pbs->left) && isBalance(pbs->right); }4.strstr()的简单实现
strstr(s1,s2)是一个经常用的函数,他的作用就是在字符串s1中寻找字符串s2如果找到了就返回指针,否则返回NULL。 下面是这个函数的一个简单实现:static const char* _strstr(const char* s1, const char* s2) { assert(s2 && s1); const char* p=s1, *r=s2; while(*p!='/0') { while(*p++==*r++); if(*r=='/0') return p; else { r=s2; p=++s1; } } return NULL; }5.链表反转
单向链表的反转是一个经常被问到的一个面试题,也是一个非常基础的问题。比如一个链表是这样的: 1->2->3->4->5 通过反转后成为5->4->3->2->1。最容易想到的方法遍历一遍链表,利用一个辅助指针,存储遍历过程中当前指针指向的下一个元素,然后将当前节点元素的指针反转后,利用已经存储的指针往后面继续遍历。源代码如下:
struct linka { int data; linka* next; }; void reverse(linka*& head) { if(head ==NULL) return; linka*pre, *cur, *ne; pre=head; cur=head->next; while(cur) { ne = cur->next; cur->next = pre; pre = cur; cur = ne; } head->next = NULL; head = pre; }还有一种利用递归的方法。这种方法的基本思想是在反转当前节点之前先调用递归函数反转后续节点。源代码如下。不过这个方法有一个缺点,就是在反转后的最后一个结点会形成一个环,所以必须将函数的返回的节点的next域置为NULL。因为要改变head指针,所以我用了引用。算法的源代码如下:
linka* reverse(linka* p,linka*& head) { if(p == NULL || p->next == NULL) { head=p; return p; } else { linka* tmp = reverse(p->next,head); tmp->next = p; return p; } }