[微软面试100题]4150

第四十三题:二叉树的非递归前中后序遍历

前序遍历:
void preorderShowTreeIterative(BSTreeNode *pRoot){
    stack<BSTreeNode*> buf;
    buf.push(pRoot);
    while(!buf.empty()){
        BSTreeNode *p=buf.top();
        buf.pop();
        cout<<p->m_nValue<<endl;
        if(p->m_pRight!=NULL)buf.push(p->m_pRight);//right first
        if(p->m_pLeft!=NULL)buf.push(p->m_pLeft);//left behind
    }
}

中序遍历:

void inorderShowTreeIterative(BSTreeNode *pRoot){
    stack<BSTreeNode*> buf;
    BSTreeNode *current=pRoot;
    while(!buf.empty() || current!=NULL){
        if(current!=NULL){
            buf.push(current);
            current=current->m_pLeft;//当前不为空,则不断往左搜索
        }else{
            current=buf.top();//左到头了,打印中,往右搜索
            buf.pop();
            cout<<current->m_nValue<<endl;
            current=current->m_pRight;
        }
    }
}

后序遍历:

void postorderShowTreeIterative(BSTreeNode *pRoot){
    stack<BSTreeNode*> traverse,visit;//使用两个栈
    traverse.push(pRoot);
    while(!traverse.empty()){
        BSTreeNode *p=traverse.top();
        traverse.pop();
        visit.push(p);//traverse栈的顶元素进visit
        if(p->m_pLeft!=NULL)traverse.push(p->m_pLeft);//左右子先后进traverse
        if(p->m_pRight!=NULL)traverse.push(p->m_pRight);
    }
    while(!visit.empty()){//显示visit所有元素
        cout<<visit.top()->m_nValue<<endl;
        visit.pop();
    }
}

第四十四题:找出重复次数最多的十条短信

1千万=10M 每条信息140char=B,总共1400MB,可以放进内存。可以用hash table计算每条信息出现的次数,然后用min heap sort来找出最多的十条。 

第四十七题:求数组的最长递减子序列(非连续子序列)

思路:使用动态规划DP,存储搜索到目前为止的最长递减子序列。搜索到新的递减子序列时,先把之前的best序列中比新序列头元素要大的元素放到新序列的前面,再开始放入新序列的开头元素。如果新的序列的长度比best的长度要大,则更新。复杂度为O(n^2)
int longestDecreaseSequence(int *a,int cnt){
    int bestSeq[cnt];//存放当前最长子序列
    int nowSeq[cnt];//存放当前正在扫描的连续下降序列
    nowSeq[0]=*a;
    int bLen=0,nLen=1;
    for(int i=1;i<cnt;++i){
        if(a[i]<a[i-1]) nowSeq[nLen++]=a[i];
 
        if(a[i]>=a[i-1] || i==cnt-1){//当序列上升时,如果now长于best则复制过去
            if(nLen>bLen){
                for(int j=0;j<nLen;++j) bestSeq[j]=nowSeq[j];
                bLen=nLen;
            }
            if(i==cnt-1)break;//最后也必须复制一遍
 
            nLen=0;
            for(int j=0;j<bLen;++j){//搜索best里面比当前新下降序列的头元素要大的元素
                if(bestSeq[j]>a[i]) nowSeq[nLen++]=bestSeq[j];//放在now的前面
                else break;
            }
            nowSeq[nLen++]=a[i];//最后才放入最新的元素
        }
    }
    for(int i=0;i<bLen;++i)cout<<bestSeq[i]<<" ";
    cout<<endl;
    return bLen;
}

网上普遍的DP方法:用一个数组记录第k个递减序列的长度和最小值。遍历到一个新元素时,搜索此元素能否加到各个递减序列中。最坏情况下复杂度为O(n^2),但使用二分查找可以把复杂度降为O(nlogn),(研究了以后发现这个算法太蛋疼就没搞了)

int tradition(int *a,int cnt){//网上传统的DP方法,只能返回最长长度.复杂度O(n^2)
    int len[cnt],maxLen=1;//len是第k个往后的最长降序列长度
    for(int i=0;i<cnt;++i)len[i]=1;
    for(int i=cnt-1;i>=0;--i){
        for(int j=i+1;j<cnt;++j){//从第i个开始往后搜索
            if(a[i]>a[j] && len[j]>=len[i])len[i]=len[j]+1;//往后搜索过程中会不断更新i的长度
        }//为了保证最后len[i]是最长的长度,只有len[j]不小于len[i]时才更新,确保len[i]不断年递增
        if(len[i]>maxLen) maxLen=len[i];
    }
    return maxLen;
}

第四十七题:二分查找

int binarySearchRecur(const int *a,const int &begin,const int &end,const int &t,int ascend=1){//1 is ascend , 0 is descend
    if(a==NULL)return -1;//defense programming; use const & to save memory
    if(begin==end)return begin;
    if((1==ascend && a[begin+(end-begin)/2]>=t) || (0==ascend && a[begin+(end-begin)/2]<=t)){
        return binarySearchRecur(a,begin,begin+(end-begin)/2,t,ascend);
    }else{
        return binarySearchRecur(a,begin+(end-begin)/2+1,end,t,ascend);//begin+end may overflow
    }
}
 
int binarySearch(const int *a,const int &begin,const int &end,const int &t,int ascend=1){
    int b=begin,e=end,m=begin+(end-begin)/2;
    if(a==NULL)return -1;//defense programming; use const & to save memory
    while(b<=e){
        if(b==e)break;
        if((1==ascend && a[m]>=t) || (0==ascend && a[m]<=t)) e=m;
        else b=m+1;
        m=b+(e-b)/2;
    }
    return b;
}

第四十八题:二分查找左移递减数列

思路:一个左移的递减序列从中点分割成两份后,一定是一份是纯递减数列,一列也是左移递减数列。
判断哪边是纯递减是看中间元素是否小于头元素。  如果要找的目标在纯递减则使用二分,否则递归自身。
int shiftedBinarySearch(int *a,int begin,int end,int t){
    const int b=begin,e=end,m=begin+(end-begin)/2;
    if(a==NULL)return -1;//defense programming; use const & to save memory
    while(b<=e){
        if(b==e)break;
        if(a[m]<=a[begin] && a[begin]>=t && a[m]<=t)
            return binarySearch(a,b,m,t,0);
        else if(a[m]<=a[begin])
            return shiftedBinarySearch(a,m+1,e,t);
        else if(a[m]>=a[begin] && a[end]<= t && a[m+1]>=t)
            return binarySearch(a,m+1,e,t,0);
        else
            return shiftedBinarySearch(a,b,m,t);
    }
    return b;
}
原文地址:https://www.cnblogs.com/iyjhabc/p/2986041.html