• [微软面试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;
    }
  • 相关阅读:
    POJ 1236 Network of Schools(强连通分量缩点求根节点和叶子节点的个数)
    文本编辑器vim和gedit
    Ubuntu安装tensorflow
    剑指offer——python【第29题】最小的K个数
    剑指offer——python【第30题】连续子数组的最大和
    剑指offer——python【第37题】数字在排序数组中出现的次数
    剑指offer——python【第28题】数组 中出现次数超过一半的数字
    剑指offer——python【第31题】整数1出现的次数
    剑指offer——python【第54题】字符流中第一个不重复的字符
    剑指offer——python【第40题】数组中只出现一次的数字
  • 原文地址:https://www.cnblogs.com/iyjhabc/p/2986041.html
Copyright © 2020-2023  润新知