[微软面试100题]1-10
第一题:把二分查找树转换为升序排序的双向链表。不能新建节点,只能改变树的指针。
void showMidTree(BSTreeNode *pRoot) { if(pRoot!=NULL) { showMidTree(pRoot->m_pLeft); cout<<pRoot->m_nValue<<endl; showMidTree(pRoot->m_pRight); } }
思路一:当我们到达某一结点准备调整以该结点为根结点的子树时,先调整其左子树将左 子树转换成一个排好序的左子链表,再调整其右子树转换右子链表。最近链接左子链表的最右结点(左子树的最大结点)、当前结点和右子链表的最左结点(右子树 的最小结点)。从树的根结点开始递归调整所有结点。
struct BSTreeNode{ BSTreeNode(){ m_pLeft=NULL; m_pRight=NULL; } bool legal(set<BSTreeNode*> &found); int m_nValue; BSTreeNode *m_pLeft; BSTreeNode *m_pRight; }; //递归建立二分查找树 BSTreeNode* buildTree(int *num,int count){ BSTreeNode *pRoot=new BSTreeNode; for(int i=0;i<count;++i){ if(i==0){ pRoot->m_nValue=num[i]; } else{ BSTreeNode *pNode=new BSTreeNode; BSTreeNode *pTmp=pRoot; while(pTmp!=NULL){ //比父节点大的分配到右边 if(pTmp->m_nValue<=num[i]){ if(pTmp->m_pRight==NULL){ pTmp->m_pRight=pNode; pTmp->m_pRight->m_nValue=num[i]; break; } else{ pTmp=pTmp->m_pRight; } } else{ if(pTmp->m_pLeft==NULL){ pTmp->m_pLeft=pNode; pTmp->m_pLeft->m_nValue=num[i]; break; } else{ pTmp=pTmp->m_pLeft; } } } } } return pRoot; } //中序遍历 就是二分查找树的升序遍历。 void showMidTree(BSTreeNode *pRoot){ if(pRoot!=NULL){ showMidTree(pRoot->m_pLeft); cout<<pRoot->m_nValue<<endl; showMidTree(pRoot->m_pRight); } } void connect(BSTreeNode *pRoot,BSTreeNode* &p){ if(pRoot!=NULL){ connect(pRoot->m_pLeft,p); //p初值为NULL,之后记录前一个值的指针 if(p!=NULL){ pRoot->m_pLeft=p; p->m_pRight=pRoot; p=pRoot; } else{ p=pRoot; } connect(pRoot->m_pRight,p); } } BSTreeNode* tree2list(BSTreeNode *pRoot){ BSTreeNode *p=NULL; connect(pRoot,p); while(pRoot->m_pLeft!=NULL){ pRoot=pRoot->m_pLeft; } return pRoot; } int main() { int num[]={10,6,14,4,8,12,16}; BSTreeNode *pRoot=buildTree(num,7); BSTreeNode *start=tree2list(pRoot); while(start!=NULL){ cout<<start->m_nValue<<endl; start=start->m_pRight; } }
貌似答案就是这个思路,还没做出来
struck minStackElem { int val; int minVal;//从栈底到此元素的最小值};
第三题:求最大子数组和,使用动态规划复杂度为O(n),题目同编程之美一样
第四题:二元树中找出和为某一值的所有路径
void BinaryTreeNode::getPath(int thisSum,int sum,deque<int> deq){ deq.push_back(this->m_nValue); //find it if(thisSum==this->m_nValue){ cout<<"find:"<<endl; while(deq.size()>0){ cout<<deq.front()<<endl; deq.pop_front(); } return; } if(this->m_nValue<thisSum){ if(this->m_pLeft!=NULL){ this->m_pLeft->getPath(thisSum-this->m_nValue,sum,deq); } if(this->m_pRight!=NULL){ this->m_pRight->getPath(thisSum-this->m_nValue,sum,deq); } } }
第五题:寻找数组中最小的K个元素
最大堆原理解释:http://blog.csdn.net/xiaoxiaoxuewen/article/details/7570621
于此,还得好好总结下,问题得这样解决:
1.先判断带不带环
2.如果都不带环,就判断尾节点是否相等
3.如果都带环,那么一个指针步长为1遍历一链表,另一指针,步长为2,遍历另一个链表。
但第3点,如果带环 但不相交,那么程序会陷入死循环。。
第八题:颠倒单向链表顺序
template<class T> link<T>::~link(){ if(this->next!=NULL){ delete this->next; } cout<<this->val<<" has been released"<<endl; } template<class T> void link<T>::append(T val){ link<T> *tmp=this; while(tmp->next!=NULL){ tmp=tmp->next; } tmp->next=new link<T>; tmp->next->val=val; cout<<tmp->next->val<<" is appended"<<endl; }
递归方法:
//技巧:使用参数传递所需的前值(以前我一般喜欢用返回值), //使用返回值传递结果(结果通常在最底层),如现在的反向链表的头指针 template<class T> link<T>* link<T>::reverse(link<T> *rnext){ if(this->next!=NULL){ link<T>* head=this->next->reverse(this); this->next=rnext; return head; } this->next=rnext; return this; }
非递归方法:
template<class T> link<T>* link<T>::reverseUnrecursive(){ link<T> *previous=NULL,*head=this,*pNext=this->next; while(head!=NULL){ pNext=head->next; head->next=previous; previous=head; head=pNext; } return previous; }
第八题:通用字符串匹配-非递归法-可输出第一个匹配的子串
跟上面一样分4种情况进行递归即可,详细看源码。我做的方法与答案的不同,但更好理解。采用先编写测试用例再编程确实非常高效!(回归测试)
第八题:翻转句子的词
第八题:查找子字符串
第八题:比较字符串,要求O(n)时间复杂度和O(1)空间复杂度
第八题:一个长为1001的数组中乱序存放1到1000的整数,除一个数外其余都不重复。只可以遍历数组一次且不可使用辅助存储,找出重复。
int a[]={1,5,2,3,4,5}; int k=0; for(int i=0;i<6;++i){ k^=a[i]; if(i<5)k^=i+1; } cout<<k<<endl;
异或的性质:同则0- A^A=0 不同则1- A^B=1;异或0不影响A^0=A;因此初始化为0.
第八题:不用乘法和加法,运算一个整数的八倍,七倍
第九题:判断整数序列是否是二元查找树后序遍历的结果
二元查找树中序:从小到大; 后序:最后的元素为中间值,前半段元素小于中间值,后半段大于中间值。
int isPostOrder(int *a,int start,int end){ if(start==end)return 1; int pivot=a[end];//最后的元素是树根,前半段小于根,后半段大于根 int mid=(end+start)/2; int i,j; for(i=start;i<mid;++i){ if(a[i]>pivot)return 0; } for(j=end-1;j>=mid;--j){ if(a[j]<pivot)return 0; } if(i!=j+1)return 0;//判断是否对称,是否二元树 return isPostOrder(a,start,mid-1) && isPostOrder(a,mid,end-1); }