网易2016实习研发工程师编程题

来源:互联网 发布:阿里云公网宽带 编辑:程序博客网 时间:2024/06/11 02:02

比较重量


小明陪小红去看钻石,他们从一堆钻石中随机抽取两颗并比较她们的重量。这些钻石的重量各不相同。在他们们比较了一段时间后,它们看中了两颗钻石g1和g2。现在请你根据之前比较的信息判断这两颗钻石的哪颗更重。
给定两颗钻石的编号g1,g2,编号从1开始,同时给定关系数组vector,其中元素为一些二元组,第一个元素为一次比较中较重的钻石的编号,第二个元素为较轻的钻石的编号。最后给定之前的比较次数n。请返回这两颗钻石的关系,若g1更重返回1,g2更重返回-1,无法判断返回0。输入数据保证合法,不会有矛盾情况出现。
测试样例:
2,3,[[1,2],[2,4],[1,3],[4,3]],4
返回: 1


按照我自己思路解出:
1、先找出所有大于g1的集合set,所有小于g1的集合set,若可以直接判断,则返回。
2、将所有未与g1、g2直接比较的,归入集合。
3、按照g2查找集合,如果存在大于g2的数在小于g1的集合内,返回1,下面类似。
4、无法比较返回0。


class Cmp {public:    int cmp(int g1, int g2, vector<vector<int> > records, int n) {        // write code here        set<int> bigg1,smallg1;        for(int i=0;i<n;++i)        {            if(records[i][0]==g1)            {                smallg1.insert(records[i][1]);//小于g1            }            else if(records[i][1]==g1)            {                bigg1.insert(records[i][0]);//大于g1            }            //可以直接判断的            if(records[i][0]==g1&&records[i][1]==g2)                return 1;            if(records[i][0]==g2&&records[i][1]==g1)                return -1;        }        for(int i=0;i<n;++i)        {            if(records[i][0]!=g1&&records[i][0]!=g2&&                    records[i][1]!=g1&&records[i][1]!=g2)            {                if(smallg1.find(records[i][0])!=smallg1.end())                    smallg1.insert(records[i][1]);                else if(bigg1.find(records[i][1])!=bigg1.end())                    bigg1.insert(records[i][0]);            }        }        for(int i=0;i<n;++i)        {            if(records[i][0]==g2)            {                if(bigg1.find(records[i][1])!=bigg1.end())  return -1;            }            if(records[i][1]==g2)            {                if(smallg1.find(records[i][0])!=smallg1.end())  return 1;            }        }            return 0;    }};

二叉树


有一棵二叉树,树上每个点标有权值,权值各不相同,请设计一个算法算出权值最大的叶节点到权值最小的叶节点的距离。二叉树每条边的距离为1,一个节点经过多少条边到达另一个节点为这两个节点之间的距离。
给定二叉树的根节点root,请返回所求距离。


解题比较复杂,思路:
1、前序遍历,保存遍历结果,以及各个节点的路径值,最大最小叶子值。
2、找出最大最小叶子在遍历结果的索引。
3、寻找最近公共祖先。按照遍历结果,如果一个在left/right后面,一个在right/left后面,则目前的节点便是结果,否则继续左或右寻找。
4、找到后将三个节点的路径值找出。


/*struct TreeNode {    int val;    struct TreeNode *left;    struct TreeNode *right;    TreeNode(int x) :            val(x), left(NULL), right(NULL) {    }};*/class Tree {public:    int getDis(TreeNode* root) {        // write code here        stack<pair<TreeNode*,int>> st;        st.push({root,0});        TreeNode *cur;        vector<int> pre,node;        vector<pair<int,int>> vp;        int maxn{0},minn{0};        while(!st.empty())//DFS--preorder        {            auto p=st.top();            cur=p.first;            vp.push_back({cur->val,p.second});            st.pop();            pre.push_back(cur->val);            if(cur->right)                st.push({cur->right,p.second+1});            if(cur->left)                st.push({cur->left,p.second+1});            if(!(cur->left||cur->right))            {                if(maxn==0&&minn==0)                {                    maxn=minn=cur->val;                }                else                {                    maxn=max(maxn,cur->val);                    minn=min(minn,cur->val);                }            }        }        stack<TreeNode*> st1;        st1.push(root);        int curpos{},maxpos{-1},minpos{-1},sz=pre.size();        for(int i=0;i<sz&&(maxpos==-1||minpos==-1);++i)        {            if(pre[i]==maxn)            {                maxpos=i;            }            if(pre[i]==minn)            {                minpos=i;            }        }        while(!st1.empty())        {            cur=st1.top();            st1.pop();            int left{-1},right{-1},leftpos{-1},rightpos{-1};            if(cur->right)            {                right=cur->right->val;                st1.push(cur->right);            }            if(cur->left)            {                left=cur->left->val;                st1.push(cur->left);            }            for(int i=curpos;i<sz;++i)            {                if(left!=-1&&pre[i]==left)                {                    leftpos=i;                }                if(right!=-1&&pre[i]==right)                {                    rightpos=i;                }            }            if(leftpos!=-1&&rightpos!=-1)            {                if(maxpos<rightpos&&minpos<rightpos)                {                    curpos=leftpos;                }                else if(maxpos>rightpos&&minpos>rightpos)                {                    curpos=rightpos;                }                else                {                    curpos=pre[curpos];//更新为对应值                    break;                }            }        }        int minl{-1},maxl{-1},fl{-1};        sz=vp.size();        for(int i=0;i<sz&&(minl==-1||maxl==-1||fl==-1);++i)        {            if(minl==-1&&vp[i].first==minn)            {                minl=vp[i].second;            }            if(maxl==-1&&vp[i].first==maxn)            {                maxl=vp[i].second;            }            if(fl==-1&&vp[i].first==curpos)            {                fl=vp[i].second;            }        }        return maxl-fl+minl-fl;    }};

看一下别人的代码:@NoYes_Li
这段java代码我看了很久,主要是被一个函数给暗算了,
maxcodec.charAt(index),他的索引是字符串的低位开始,类似数组,不要从自己的低位!
为什么二进制编码可以呢,显然,在这里,他将相同前缀去掉就是找到了父节点的编码(他的编码是左走加0,右走加1),在这里除去前缀的长度就是该节点到父节点的距离,两者距离相加就是路径长度了。


//典型的二进制编码题,算出叶子节点二进制编码,再比编码,计算后缀长度和import java.util.*;/*public class TreeNode {    int val = 0;    TreeNode left = null;    TreeNode right = null;    public TreeNode(int val) {        this.val = val;    }}*/public class Tree {    private int max=0;    private int min=99999;    private StringBuilder maxcodec;    private StringBuilder mincodec;        void PreOrder(TreeNode T,char code,StringBuilder codec){        if(T!=null){                       codec.append(code);            if(T.left==null && T.right==null)            {                if(max<T.val)                {                    max=T.val;                    maxcodec = codec;                }                if(min>T.val)                {                    min=T.val;                    mincodec = codec;                }            }            PreOrder(T.left,'0',new StringBuilder(codec));            PreOrder(T.right,'1',new StringBuilder(codec));        }    }    public int getDis(TreeNode root) {        PreOrder(root,'0',new StringBuilder());        int index=0;        for(index=0; index<(maxcodec.length()>mincodec.length()?maxcodec.length():mincodec.length());index++)        {            if(maxcodec.charAt(index)!=mincodec.charAt(index))                break;        }        return (maxcodec.substring(index).length()+mincodec.substring(index).length());        // write code here    }};

寻找第K大


有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数。
给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在。
测试样例:
[1,3,5,2,2],5,3
返回:2


类快排思想:
1、找出枢纽点,比如按照三点中值可以找出。
2、当数组比较小时,可以采取插入排序等寻找,此处可以改进。
3、将中值放在数组尾部前,可以将剩余元素方便归类。
4、还原中值,开始递归。


代码反思:

vector<int> small(a.begin(),a.begin()+i),big(a.begin()+i+1,a.end());        int bsz=big.size(),ssz=small.size();        if(bsz>=K){            return findKth(big,bsz,K);        }        else if(bsz==K-1){            for(int i=0;i<14;++i){                cout<<a[i]<<endl;            }            return a[i];        }        else{            return findKth(small,ssz,K-bsz);        }

最开始我的递归部分是这样写的,妄想像快排一样,忽略已经定序的枢纽元素,但是,结果错误。后来将该元素归入大的一类才正确,经过IDE调试,发现如果不考虑该元素,就相当与后面你的数组里面少了一个元素,这是致命的。可能会在后面算大小与K比较时候出现问题。
如:
1,2,2,4,3,7,8,9,1,10,8,9找第7
中值7,此时1,2,2,4,3,1一组,8,9,10,8,9一组
1,2,2,4,3,1找第7-5=2
中值1,此时1一组,2,2,3,4一组
得到3。错误。
实际应该是4。
中值7,此时1,2,2,4,3,1一组,7,8,9,10,8,9一组
1,2,2,4,3,1找第7-6=1
中值1,此时1一组,2,2,3,4一组
得到4。正确。
此处应该把值放入,但是依旧可以那么返回。

后期注释掉的代码应该是多余的。


class Finder {public:    int findKth(vector<int> a, int n, int K) {        // write code here     //   if(n==0)    return 0;后期注释掉的,应该不需要     //   if(n==1)    return a[0];        if(n<10){            sort(a);            return a[K-1];        }        int pivot=median3(a,n);        int i=0,j=n-2;        for(;;){            while(a[++i]<pivot);            while(pivot<a[--j]);            if(i<j){                swap(a[i],a[j]);            }              else{                break;            }        }        swap(a[i],a[n-2]);        vector<int> small(a.begin(),a.begin()+i),big(a.begin()+i,a.end());        int bsz=big.size(),ssz=small.size();        if(bsz>=K){            return findKth(big,bsz,K);        }        else{            return findKth(small,ssz,K-bsz);        }    }private:    int median3(vector<int> &a,int n){        int mid=n/2;        if(a[mid]<a[0])            swap(a[mid],a[0]);        if(a[n-1]<a[0])            swap(a[0],a[n-1]);        if(a[n-1]<a[mid])            swap(a[n-1],a[mid]);        swap(a[mid],a[n-2]);        return a[n-2];    }    void sort(vector<int> &a){//select_sort        int sz=a.size();        for(int i=0;i<sz;++i){            int maxp=i;            for(int j=i+1;j<sz;++j){                if(a[j]>a[maxp]){                    maxp=j;                }            }            swap(a[i],a[maxp]);        }    }};
0 0
原创粉丝点击