阿里巴巴2016校园招聘 研发工程师(三)详解

版权声明:听说这里让写版权声明~~~ https://blog.csdn.net/f_zyj/article/details/79216923

##单选题
#####1、从1,2,3,4…8,9 里任意选择一部分数(至少1个),能得到多少种不同的乘积。

A. 144
B. 148
C. 152
D. 156
E. 160
F. 164

######解析:
首先分解因子: 1 2 . . . 9 = 2 7 3 4 5 7 1 * 2 * ... * 9 = 2^7 * 3^4 * 5 * 7

所以因子组合总数 = 8 5 2 2 = 160 = 8 * 5 * 2 * 2 = 160

2 7 3 0 2^7 * 3^0 2 0 3 4 2^0 * 3^4 这两种情况不存在,因为有一个 2 2 6 6 提供的,有一个 3 3 也是 6 6 提供的,另外这两种情况与 5 5 7 7 的组合分别有 4 4 种,所以答案 = 160 2 4 = 152 = 160 - 2 * 4 = 152

#####2、商品推荐场景中过于聚焦的商品推荐往往会损害用户的购物体验,在有些场景中,系统会通过一定程度的随机性给用户带来发现的惊喜感。假设在某推荐场景中,经计算A和B两个商品与当前访问用户的匹配度分别为0.8和0.2分,系统将随机为A生成一个均匀分布于0到0.8的最终得分,为B生成一个均匀分布于0到0.2的最终得分,那么最终B的分数大于A的分数的概率为_____。

A. 0.0625
B. 0.125
C. 0.1875
D. 0.375
E. 0.25
F. 1/3

######解析:
十分简单的一个题,由于是随机分布,也就是均匀分布, A A 1 4 \frac{1}{4} 概率分数在 0 0.2 0 \sim 0.2 之间,那么在这个分数段 A A 1 2 \frac{1}{2} 概率低于 B B 的分数,总的概率为 1 4 1 2 = 1 8 = 0.125 \frac{1}{4} * \frac{1}{2} = \frac{1}{8} = 0.125

#####3、有甲、乙、丙三位员工分别负责前端、后端、数据、算法、测试、运维。每人负责两项。已知:数据和前端住在一起 甲是三人中最年轻的 前端和丙有空一起下棋 后端比算法年长,又比乙年轻 三人中最年长的住得最远 那么,三人分别负责____。

A. 甲-前端&测试;乙-算法&运维;丙-后端&数据
B. 甲-后端&算法;乙-前端&运维;丙-测试&数据
C. 甲-前端&运维;乙-测试&算法;丙-后端&数据
D. 甲-算法&数据;乙-测试&前端;丙-后端&运维
E. 甲-前端&算法;乙-后端&运维;丙-测试&数据
F. 甲-前端&算法;乙-测试&运维;丙-后端&数据

######解析:
这种问题就是画个表格推导一下的问题。

*
前端 Y N N
后端 N N Y
数据 N N Y
算法 Y N N
测试 N Y N
运维 N Y N

主要推断依据:
甲的年龄 < < 丙的年龄 < < 乙的年龄;
算法的年龄 < < 后端的年龄 < < 乙的年龄;
丙不会前端;
甲和丙住在一起;
数据和前端住在一起。

#####4、有一个程序中有A,B,C三个线程同时对一个文件进行读写操作,其中的A,B是写进程只负责往里面写数据,C是读线程,同时把读取的数据从文件中删除,A线程单独写满文件需要10个小时,B单独写程序需要6小时,C线程需要15小时才能读取完整个文件,不考虑三个线程之间的相互影响的情况下现在____小时才能写满文件。

A. 5
B. 6
C. 5.5
D. 4.5
E. 4.8
F. 5.3

######解析:
A A 每小时写 1 10 \frac{1}{10} B B 每小时写 1 6 \frac{1}{6} C C 每小时读 1 15 \frac{1}{15} ,所以三者同时工作每小时写 1 10 + 1 6 1 15 = 1 5 \frac{1}{10} + \frac{1}{6} - \frac{1}{15} = \frac{1}{5} ,所以一共需要 5 5 个小时才能写满。

#####5、如果下列的公式成立:84*148=B6A8。则采用的是____进制表示的。

A. 15
B. 11
C. 12
D. 14
E. 16
F. 以上都不对

######解析:
84 84 148 148 按照不同进制进行乘法获得结果是否等于 B 6 A 8 B6A8 ,也可以都转化为十进制进行计算。

这里只举例 12 12 进制转 10 10 进制的计算, 84 84 十二转十是 100 100 148 148 200 200 ,乘积是 20000 20000 ,而 B 6 A 8 B6A8 正是 20000 20000

##多选题
#####6、下面是折半查找的实现,data是按升序排列的数据,x是查找下标,y是查找的上标,
#####v是查找的数值,返回v在data的索引,若没找到返回-1。代码不正确是____。

public int bsearch(int[] data, int x, int y, int v) {
    int m;
    while(x<y){ //1
        m = x + (y-x)/2; //2
        if(data[m] == v) return m; //3
        else if(data[m] > v) y = m; //4
        else x = m; //5
    }
    return -1; //6
}

A. 1
B. 2
C. 3
D. 4
E. 5
F. 6

######解析:
首先, 4 4 大于的时候,应该改为 y = m 1 y = m - 1

其次, 5 5 小于的时候,可以改成 x = m + 1 x = m + 1

还有就是, 1 1 应该改成 x &lt; = y x &lt;= y ,避免漏判,例如 1 , 2 1, 2 查找 2 2 x = 1 , y = 2 , m = 1 x = 1, y = 2, m = 1 ,因为 d a t a [ m ] &lt; 2 data[m] &lt; 2 所以 x = 2 x = 2 ,此时 x = y x = y ,并且 x x 就是要返回的值,如果不改成 x &lt; = y x &lt;= y ,那么将会返回 1 -1 ,显然是错误的。

##单选题
#####7、如果我国希望在30年后实现经济翻翻,并且假设我国经济增长速度每年都保持相同,那么至少需要每年保持____增长速度才可实现目标。

A. 1.5%
B. 1.8%
C. 2%
D. 2.4%
E. 3.3%
F. 7%

######解析:
( 1 + x % ) 30 &gt; = 2 {(1 + x\%)}^{30} &gt;= 2 ,不过问题来了,在没有计算机的笔试题情况下,这个公式等于废话……

这时候需要引进一个法则—— 72 72 法则,复利为 1 % 1\% 的时候,需要 72 72 年会翻倍(估算)。那么估算时,如果利息为 x x% 时,翻倍的时间即为 72 x \frac{72}{x} 年,所以只需要求 72 x &lt; = 30 \frac{72}{x} &lt;= 30 ,也就是 x &gt; = 72 30 = 2.4 x &gt;= \frac{72}{30} = 2.4

#####8、关于线程和进程,不正确的描述是____。

A. 进程的隔离性要好于线程
B. 线程在资源消耗上通常要比进程轻量
C. 不同进程间不会共享逻辑地址空间
D. 同一个进程的线程之间共享内存,包括堆和栈
E. 进程间有途径共享大量内存中的数据
F. 线程间通讯可以通过直接访问全局变量,或者使用进程间通讯的机制(IPC)

######解析:
区别:

  1. 包含关系:一个程序至少有一个进程,一个进程至少有一个线程。
  2. 内存共享:进程在执行过程中拥有独立的内存单元(一个进程崩溃后,在保护模式下不会对其它进程产生影响);而多个线程共享进程提供的内存(拥有自己的私有栈空间只是作为运行需要的极少内存),从而极大地提高了程序的运行效率,但一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮。
  3. 执行过程:进程独立执行;线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
  4. 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。

通信:
进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是共享内存区。但是,系统空间却是“公共场所”,所以内核显然可以提供这样的条件。除此以外,那就是双方都可以访问的外设了。在这个意义上,两个进程当然也可以通过磁盘上的普通文件交换信息,或者通过“注册表”或其它数据库中的某些表项和记录交换信息。广义上这也是进程间通信的手段,但是一般都不把这算作“进程间通信”。因为那些通信手段的效率太低了,而人们对进程间通信的要求是要有一定的实时性。
进程间通信主要包括管道, 系统IPC(包括消息队列,信号量,共享存储), SOCKET。

#####9、以下程序输出结果是____。

class A
{
public:
    virtual void func(int val = 1)
    { std::cout<<"A->"<<val<<std::endl;}
    virtual void test()
    {func();}
};
class B : public A
{
public:
    void func(int val=0)
    {std::cout<<"B->"<<val<<std::endl;}
};
int main(int argc ,char* argv[])
{
    B*p = new B;
    p->test();
    return 0;
}

A. A->0
B. B->1
C. A->1
D. B->0
E. 编译出错
F. 以上都不对

######解析:
虚函数的的缺省参数是静态绑定,绝不重新定义继承而来的缺省参数。

#####10、两人在一个n个点的无向完全图上进行游戏,每次可以选择当前图中两个端点度数奇偶性相同的边删除,谁不能操作谁输,则在n=1,2,3,…,9,10中,有____个图先手有必胜策略。

A. 2
B. 3
C. 4
D. 5
E. 6
F. 7

######解析:
N N 个点的无向完全图边数为: N ( N 1 ) 2 \frac{N * (N - 1)}{2}

先手获胜必须总数为奇数, N = 1 10 N = 1 \sim 10 代入公式,为奇数的只有 N = 2 , 3 , 6 , 7 , 10 N = 2, 3, 6, 7, 10 5 5 个。

对于这种博弈论问题,比较简单的形式可以采取手画几个样例找找规律的策略,一般上是可以找到比较明显规律的,这个题的规律就是受边数奇偶性的影响。

#####11、在1,2,3,…,999,1000中,有____个数各位数之和模10等于0。

A. 99
B. 100
C. 101
D. 150
E. 200
F. 201

######解析:
0 99 0 \sim 99 一共 9 9 个数符合条件, 19 28 . . . 91 19、28、...、91

100 999 100 \sim 999 如果百位和十位确定,那么个位就确定了。百位可以取 1 9 1 \sim 9 ,十位可以取 0 9 0 \sim 9 ,所以 100 999 100 \sim 999 满足条件的为 9 10 = 90 9 * 10 = 90

总和就是 99 99

#####12、将森林转换为对应的二叉树,若在二叉树结点中,结点m是结点n的双亲结点的双亲结点,则在原来的森林中,m和n可能具有的关系是____。
#####1)父子关系
#####2)m的双亲结点与n的双亲结点是兄弟关系
#####3)兄弟关系

A. 只有3
B. 1和3
C. 1和2
D. 1、2和3
E. 只有1
F. 只有2

######解析:
这是往年的一道考研题,可以通过举特例来证明。

首先树转化为二叉树,我们可以采用左儿子右兄弟原则,假设树根结点下有三个结点一共四个结点构成树,那么转化为二叉树时,如果根是 u u ,第二个儿子是 v v ,则证明可以是父子关系;如果第一个儿子是 u u ,第三个儿子是 v v ,则证明可以是兄弟关系。

描述

Ps. 此为盗图,图片来源 米兰的小铁匠114

#####13、函数func的定义如下:

void func(const int& v1, const int& v2)
{
    std::cout << v1 << ' ';
    std::cout << v2 << ' ';
}
在Visual Studio开发环境下, 以下代码输出结果为____。
int main (int argc, char* argv[])
{
    int i=0;
    func(++i,i++);
    return 0;
}

A. 0 1
B. 1 2
C. 2 1
D. 2 0
E. 0 2
F. 1 0

######解析:
这个题考点是参数传递的入栈顺序以及两种自增的区别。

首先参数入栈是从右往左,先处理 i + + i++ ,因为 i + + i++ 是先计算再自增,并且返回值是一个临时变量,所以传入的是值为 0 0 一个临时变量的引用,接着处理 + + i ++i ,是先自增后计算,所以传入的是真实的 i i 的引用。自然而然,结果是 2   0 2\ 0

这个题关键还是和编译器有关,不同的编译器结果可能不同,因为虽然定义了入栈顺序为从右往左,但是,计算顺序并未定义,不同的编译器对这部分的优化可能不尽相同。

#####14、将整数数组(7-6-3-5-4-1-2)按照堆排序的方式原地进行升序排列,请问在第一轮排序结束之后,数组的顺序是_____。

A. 2-6-3-5-4-1-7
B. 6-2-3-5-4-1-7
C. 6-5-3-2-4-1-7
D. 1-5-3-2-4-6-7
E. 5-4-3-2-1-6-7
F. 5-1-3-2-4-6-7

######解析:
堆排序是每次将无序区第一个元素和最后一个元素进行交换,并且最后一个元素划分到有序区,然后将无序区调整为符合堆的序列,一轮操作结束,继续重复上述操作,直到整个序列都划分到有序区。

那么初始序列 7   6   3   5   4   1   2 7\ 6\ 3\ 5\ 4\ 1\ 2 是满足大顶堆的,直接交换,得到 2   6   3    5   4   1   7 2\ 6\ 3\ \ 5\ 4\ 1\ 7 ,接着调整无序区可得 6   5   3   2   4   1   7 6\ 5\ 3\ 2\ 4\ 1\ 7 ,第一轮排序结束。

#####15、二进制值0.00110011001100110011001100110011 转换成10进制后最接近____。

A. 0.1
B. 0.15
C. 0.2
D. 0.22
E. 0.25
F. 0.3

######解析:
二进制转换为十进制:不同位的值 * 该位的权值的乘积之和。小数点后第一位的权值为 2 1 2^{-1} ,第二位的权值为 2 2 2^{-2} ,……。

所以本题小数点后的前两个 1 1 对应的权值分别是 2 3 2^{-3} 2 4 2^{-4} ,这两个的和为 0.1875 0.1875 ,估算这串二进制转换为十进制为 0.2 0.2 左右。

#####16、假设基准值为数组首元素的快速排序,要使得数组满足非降序排列,下列数据分布导致快排算法效率最低的是____。

A. 2-6-3-7-5-1-4
B. 6-2-3-5-4-1-7
C. 7-5-3-2-4-1-6
D. 1-5-7-2-4-6-3
E. 1-2-3-4-5-6-7
F. 4-1-3-7-5-6-2

######解析:
快排的平均复杂度为 O ( n l o g n ) O(nlogn) ,但是在极端情况下,复杂度会降低到 O ( n 2 ) O(n^2) ,所以快排适合用于对随机序列进行操作。

那么什么是快排的极端情况呢?

当序列基本有序时,快排效率极低,属于极端情况。快排每一趟都是 O ( n ) O(n) ,基本无序情况下,快排递归深度为 O ( l o g n ) O(logn) ,当基本有序时,快排递归深度退化到 O ( n ) O(n) ,复杂度变为 O ( n 2 ) O(n^2)

#####17、进程P1和P2,资源A和B,进程对资源的操作定义如下:读取资源A:rA;读取资源B:rB;写入资源A:wA;写入资源B:wB;同时规定,进程读取某一资源前,必须加上共享锁,写入某一资源前必须加上排他锁;资源在被进程加共享锁时,可以被其他进程继续加共享锁,但不能加排他锁;资源在被进程加排他锁时,其他进程无法加锁。进程完成全部操作后释放锁。进程P1和进程P2并发执行,如下哪种运行序列可能会出现死锁_____。

A. P1(rA->rB), P2(rA->wB)
B. P1(rA->rB), P2(wA->rB)
C. P1(wB->rA), P2(rA->rB)
D. P1(wB->rA), P2(wA->rB)
E. P1(wA->wB), P2(wA->wB)
F. P1(wA->rB), P2(wA->wB)

######解析:
死锁的四个必要条件:
资源独占 不可剥夺 请求和保持 循环等待

D D 选项 P 1 P1 独占 B B P 2 P2 独占 A A ,加有排他锁,而 P 1 P1 想要读 A A P 2 P2 想要读 B B ,造成请求保持,循环等待,形成死锁。

#####18、一人以d元在淘宝买入n套《三体》,d为正整数,其中两套他以成本一半送给朋友,余下的每套高于原价8元卖出,加上送给朋友的两套,如果全部利润是72元,那么n最小可能是____。

A. 18
B. 17
C. 15
D. 13
E. 12
F. 10

######解析:
假设每本 a a 元,送朋友 2 2 本赔了 a a 元,剩下 n 2 n - 2 本,赚了 ( n 2 ) 8 (n - 2) * 8 元。

净利 ( n 2 ) 8 a = 72 (n - 2) * 8 - a = 72 ,即 8 n a = 88 8 * n - a = 88 ,由于 a &gt; 0 a &gt; 0 ,所以 n &gt; 11 n &gt; 11 ,最小为 12 12

#####19、有一个类B继承自类A,他们数据成员如下:

class A {
...
private:
   int &a;
};
class B : public A {
...
private:
     int a;
public:
     const int b;
     A c;
     static const char* d;
     A* e;
};

#####则构造函数中,成员变量一定要通过初始化列表来初始化的是____。

A. b c
B. b c e
C. b c d e
D. c e
E. b d
F. b e

######解析:
构造函数初始化时必须采用初始化列表一共有三种情况,
1)需要初始化带有引用的类对象(继承时调用基类构造函数);
2)需要初始化 c o n s t const 修饰的类成员 ;
3)需要初始化引用成员数据。

另外, s t a t i c static 修饰的变量在类外初始化。

#####20、下面线程间的通讯机制中,关键路径上不会产生系统调用从而减少用户态到内核态的上下文切换的是____。

A. pthread_spin_lock
B. pthread_mutex
C. 信号量
D. pthread_rwlock
E. 管道
F. 消息队列

######解析:
p t h r e a d _ s p i n _ l o c k pthread\_spin\_lock ,自旋锁。在进入阻塞队列之前先跑几个循环,然后再去尝试获取锁,直到自旋的次数超过阈值,才进入阻塞队列,此时才切换状态。自旋锁不会引起调用者睡眠,如果自旋锁已经被其他执行单元保持调用者就一直循环在那里,看是否自旋锁的保持者已经释放了锁,因此不会导致线程的状态切换(用户态 - &gt; &gt; 内核态)。

p t h r e a d _ m u t e x pthread\_mutex ,互斥锁。不会忙等,得不到锁会选择 s l e e p sleep ,但是 s l e e p sleep 时会陷入到内核态,需要昂贵的系统调用。

p t h r e a d _ r w l o c k pthread\_rwlock ,读写锁。用来解决读者写者问题的,读操作可以共享,写操作是排他,读可以有多个在读,写只有唯一个在写,同时写的时候不允许读。

信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在那里)。

管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。

消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

猜你喜欢

转载自blog.csdn.net/f_zyj/article/details/79216923