C++面试我爱编程

阿里巴巴2017实习生招聘研发工程师C&C++笔试题

2017-07-22  本文已影响159人  GeekerLou

阿里巴巴2017实习生招聘研发工程师C/C++笔试题,包括选择题和编程题。

一、选择题

1.(单项选择题)

下面关于C/C++的说法,正确的选项是

答案:C

解析

A:C语言要求变量必须先定义,然后才能使用,光声明之后是不能直接拿来用的。

B:可以不指定大小,有编译器去识别,例如char [] s={‘a’, ‘b’, ‘c’};

C:C++虚函数的实现机制在于继承体系下的动态绑定,是CPP的特性,C语法无法模拟。

D:优先调用全局的普通函数
函数模板与同名的非模板函数重载时候,调用顺序:
寻找一个参数完全匹配的函数,如果找到了就调用它
寻找一个函数模板,将其实例化,产生一个匹配的模板函数,若找到了,就调用它
若1,2都失败,再试一试低一级的对函数的重载方法,例如通过类型转换可产生参数匹配等,若找到了,就调用它
若1,2,3均未找到匹配的函数,则是一个错误的调用

E:STL容器的迭代器end()返回容器的最后一个元素后移位置的迭代器

2.(单项选择题)

Markdown

答案:C

解析

Markdown

3.(单项选择题)

一个电梯载有12人从地下一层向上升,每个人都可以在电梯到达一层到五层中任意一层出电梯,到达6层时电梯已经没人了,一共有多少种出电梯的情况(每个人出了电梯不能再进,所有人看做相同人)?

答案:E

解析

注意本题将所有人看做是相同的人,与常做的题“4封不同的信投往3个信箱,共有多少种投法的题不一样”。

对于本题,可以将题目转化为12个球中间插4个板,分成5份的问题,但是题意要求两个板之间的球个数可以为0,所以增加五个球,在17个球之间插四个板,答案为C(16,4)=16151413/(4321)=1820种方式。

4.(单项选择题)

请阅读下面代码,判断可被垃圾回收的对象。

public class TestGC{
    private static TestGC m_t;

    public static assign(TestGC t)
    {
        m_t=t;
    }

    public void clear(TestGC t)
    {
        t=null;
    }

    public static void main(String[] args)
    {
        TestGC t1=new TestGC();
        TestGC t2=new TestGC();
        TestGC t3=new TestGC();

        t1.assign(t2);
        t1=null;
        t2=null;
        t3.clear(t3);

        System.out.println("This point");
    }
}

当程序执行到“System.out.println("This point");”这行时,可被虚拟机回收的对象有:

答案:E

解析

在编译过程中作为一种优化技术,Java 编译器能选择给实例赋 null 值,从而标记实例为可回收。

5.(单项选择题)

请阅读下面代码,计算运行结果:

public class Person{
    private int i=1;

    public Person()
    {
        System.out.print("P");
    }

    public void print()
    {
        System.out.print(i);
    }
}

public class Friend{
    public Friend()
    {
        System.out.print("F");
    }
}

public class Son extends Person{
    private Friend f=new Friend();

    public Son()
    {
        System.out.print("S");
    }

    public void print()
    {
        int i=2;
        System.out.print(i);
    }

    public static void main(String[] args)
    {
        Person s=new Son();
        s.print();
    }
}

以上程序的运行结果是:

答案:B

解析

Java中构造函数的执行顺序:

  1. 内部静态对象的构造函数
  2. 父类的构造函数
  3. 内部普通对象的构造函数
  4. 该类本身的构造函数

6.(单项选择题)

请阅读下面代码,计算运行结果:

public class TestEx{
    public static int test(String StrL,String StrR) throws Exception 
    {
        int iL,iR,iRet=-1;

        try{
            iL=Integer.parseInt(StrL);
            iR=Integer.parseInt(StrR);
            iRet=iL/iR;
        }catch(NumberFormatException e){
            System.out.print("N");
        }catch(ArithmeticException e){
            System.out.print("A");
            throw new Exception("Input value error");
        }finally{
            System.out.print("F");
        }
        return iRet;
    }

    public static void main(String[] args)
    {
        try{
            test("100","abc");
            test("5","0");
        }catch(Exception e){
            System.out.print("E");
        }
    }
}

以上程序的运行结果是

答案:B

解析

“test("100","abc");”执行后,“abc”转换为数字发生异常,被“catch(NumberFormatException e)”捕获,输出“N”,接下来执行“finally”块,输出“F”;test("5","0");

转换为数字正常,但是在做除法的时候发生除零异常,被“catch(ArithmeticException e)”捕获,输出“A”,接下来执行“finally”块,输出“F”。

最后,由于两个test函数被try语句块包围,而且发生了异常,会被随后的“catch(Exception e)”捕获,输出“E”。

因此,最终的输出结果为“NFAFE”,B选项正确。

7.(单项选择题)

public class TestFinally{
    public static void main(String[] args) throws InterruptedException
    {
        Runnable s=new Runnable(){
            public void run()
            {
                try{
                    System.out.print("线程开始执行");
                    Thread.sleep(1000);
                    System.out.print("线程执行完毕");
                }catch(InterruptedException e){
                    System.out.print("睡眠中发生了中断");
                }finally{
                    System.out.print("finally块被调用了");
                }
            }
        };
        Thread thread=new Thread(s);
        thread.setDaemon(true);
        thread.start();
        Thread.sleep(500);
    }
}

程序执行后,输出的内容最有可能是以下哪种情况:

答案:D

8.(单项选择题)

假设一棵高度为N的平衡二叉树,从树中随机选择一个节点,该节点为叶子节点的概率可能为

答案:D

解析

平衡二叉树中,叶子节点的比例最小为50%(一个根节点加一个左子节点),最大为100%(只有一个根节点)。

9.(单项选择题)

以下说法正确的是()

#include <iostream>

int f(int i){
    if(i<=0){
        return 1;
    }
    return i*f(i-1);
}

int main()
{
    for (size_t i = 10; i >= 0; --i)
    {
        std::cout<<f(i)<<std::endl;
    }
    return 0;
}

答案:D

解析

f(i)对于i<=0时进入死循环。

10.(单项选择题)

一位阿里巴巴的员工每天8:30-9:00去上班,根据堵车情况不同大概10-30分钟到公司,假设他出门时间和路上的时间都是独立的均匀分布,他在9:00前到达公司的概率是多少?

答案:B

解析

Markdown
P=(1/2*20*20)/20*30=1/3

11.(单项选择题)

有一组记录排序码(1 9 6 2 5 4 7 3) 需要进行堆排序, 请问在堆化(小根堆)之后, 堆所对应的二叉树的后序遍历序列为:

答案:B

解析

最小堆:先以数组顺序构建一棵完全二叉树,再从第n/2 +1个元素开始构建最小堆,再进行中序遍历。本例中就是从第5个元素5开始进行调整。具体的堆调整过程如下图(a)-(d)所示:

Markdown

最终小根堆化后的序列为(1 2 4 3 5 6 7 9),对其进行后序遍历后的结果为(9 3 5 2 6 7 4 1),故而本题的B选项正确。

12.(单项选择题)

假设Linux中有个/tmp/test目录,权限为drwxrw-r--,以下描述正确的是

答案:C

解析

文件的组成员拥有读权限,因而可以执行ls命令进行查看。
文件的组成员没有执行权限,因而无法执行A、D、F的指令操作。
文件的非组成员没有执行权限,因而无法执行B、E操作。

13.(单项选择题)

A和B两个团队在合作p项目,B团队做p项目的子项目p1,A团队做子项目p2,A和B的主管不是同一个人,后来p1项目衍生出来一个附属项目s,B团队做了一段时间后,B团队由于有其他紧急项目,B团队的主管M让B团队的兄弟团队C团队来做s项目,同时p1项目也调走了几个人,A团队不开心,这干扰了A团队在p2项目中的项目进度。而且A团队由于之前跟C团队合作不顺畅,不是很认可C团队的能力。A团队以下做法中最不恰当的是:

答案:E

解析

感觉F选项也不是很靠谱。

14.(单项选择题)

下列各项不属于性能关注点的是

答案:E

解析

E选项属于应用异常,而不是应用性能,其他的选项都是应用的性能。

15.(单项选择题)

Markdown
答案:F

解析

Markdown

16.(单项选择题)

小明的复活节礼物是4只彩蛋,每个彩蛋上写了一行字:第一个彩蛋:“所有的彩蛋中都有水果糖”;第二个彩蛋:“这个彩蛋里面有棉花糖”;第三个彩蛋:“这个彩蛋里没有巧克力”;第四个彩蛋:“有些彩蛋中没有水果糖”。如果其中只有一句真话,那么以下哪项为真?

答案:D

解析

第一个彩蛋中的描述与第四个彩蛋的描述互斥,由于只有一句真话,那么真话必然在第一个彩蛋和第四个彩蛋中诞生。那么第二个彩蛋和第三个彩蛋的描述必然是假话,从而可以推出:第二个彩蛋中没有棉花糖,第三个彩蛋中有巧克力。因此本题正确的选项四D。

17.(单项选择题)

36辆赛车参加比赛,赛程车速是定值,但每个赛车车速各不相同。当前只有6个赛道,无法计时,每场只能知道6辆车的相对快慢,请问最少几场比赛可以找出36辆车速度最快的前3名?

答案:C

解析

首先,36辆赛车分成6组赛跑,需要赛6场,每场取前三。
其次,将每组第一名拉出来跑一次,需要加赛1场,按照每组第一名的排列每组,也就是

A1 A2 A3

B1 B2 B3

C1 C2 C3

D1 D2 D3

E1 E2 E3

F1 F2 F3

此时也就是表示每一排由快到慢3个人,第一列由快到慢。总共只需要最快的三个人,4-6排都不可能,然后C2、C3也不可能,因为A1 B1 C1都比他们快,B3也不可能,因为A1 B1 B2都比他快,A1一定是最快的,OK,只剩下5个人需要比一下2、3名,再跑一次,需要加赛1场。

因此,最少需要的场次位6+1+1=8场。

18.(单项选择题)

假定存在A(mbr_id,name),B(prd_id,mbr_id,prd_name)两个表,以下六个选项的SQL的分别运行,哪个的结果与其他5项不一致?

答案:E

解析

考查数据库表的左连接与右连接的特性。
将E选项改为:

select count(distinct B.prd_id) from A Left outer join B on A.mbr_id = B.mbr_id AND B.mbr_id is not null;

这样,该语句就和其他语句的功能一样了。

19.(单项选择题)

设一棵完全二叉树共有799个节点,则在该二叉树中的叶子节点数为:

答案:C

解析

799=1+2+4+8+16+32+64+128+256+288

因此叶子节点的个数是288+256-288/2=400

2n-1=799,则n=400

20.(单项选择题)

下面程序的输出是()

#include <iostream>

class A{
public:
    A(){
        std::cout<<"A()"<<std::endl;
    }
    ~A(){
        std::cout<<"~A()"<<std::endl;
    }
};

class B: public A{
public:
    B(){
        std::cout<<"B()"<<std::endl;
    }
    ~B(){
        std::cout<<"~B()"<<std::endl;
    }
};

int main()
{
    A *pa=new B;
    delete pa;
    B *pb=new B;
    delete pb;
    return 0;
}

答案:A

解析

1)“A *pa=new B;”
用B类初始化A类的指针,使用new创建B类对象时,由于B类公有继承自A类,因而优先调用基类A的构造函数,输出“A()”再调用子类B的构造函数,输出“B()”。在完成B类对象创建后,利用赋值语句,将创建好的B类对象用来初始化A类的指针pa,此时pa完全是一个A类的指针,与用new A创建的A类指针别无二致,加上A类的析构函数不是虚函数,不存在动态绑定的问题,因而在执行“delete pa;”语句之后,只会析构掉pa指针所指向的对象,调用A类的析构函数,输出“~A()”。

2)“B *pb=new B;”
用B类初始化B类的指针,使用new创建B类对象时,由于B类公有继承自A类,因而优先调用基类A的构造函数,输出“A()”再调用子类B的构造函数,输出“B()”。接着执行语句“delete pb”,析构掉B类指针所指向的对象,由于B类公有继承自A类,析构函数的调用顺序与构造函数相反,因而先调用B类的析构函数,输出“~B()”,再调用A类的析构函数,输出“~A()”。

二、 编程题

1. (简答题)

做股票的人总会忍不住幻想:如果知道明天怎样就好了。那么问题来了,如果打开上帝视角,你最好能做到怎样?

真实的世界的股票交易规则太复杂,我么这里做一些简化。首先我们假设有N个股票和M个交易期。可以认为在单个交易期内所有股票的价格都是恒定的。股票卖出需要缴纳交易额的P倍的印花税。股票可以零碎地买卖,即你买个0.01股也是可以的。我们这个市场没有停牌,也没有休市,没有涨涨停停,没有买空卖空,没有分红,而且股票价格也不对跌到零。

举个例子,假设你用手里的一元钱买了个股票。这个股票第一期1元/股,你买入之后手上有1股股票和0元现金。这个股票在第二期涨到2元/股,那么这时你卖出1股就获得了2元(税前),扣除10%的印花税,你手上没有股票却有1.8元现金。

如果你在一开始有1元现金,在M个交易期之后,你最多能持有多少现金?

解题思路

要么啥都不买,要么就全都买一种股票,这样才能收益最大化。

动态规划:从第一个交易期往后递推就可以了,维护两个数组,第一个表示某交易期后可以获得的最大现金,第二个采用二维数组,表示某交易期后能够获得的某股最大股票数量。用第k-1交易期的数组值来更新第k交易期的数组值。

2.(简答题)

多多岛上有很多小火车,在提茅斯机房由燕来的放射性火车库排列改成了新的车库,每个车库只能存放一辆小火车,每个小火车进到车库只能单行。每个小火车出车库由一个天车把移动钢轨放到车库前,然后把该列上的小火车从下而上优先出库。你能帮胖总管实现火车出站调度吗?

上一篇下一篇

猜你喜欢

热点阅读