A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 西安-就业部 于 2016-4-24 17:53 编辑

阿里体验卡已充值,小灰灰带你体验变态社招
                                                                 (参与面试者
:就业部-小灰灰)

       前言:对于阿里自己曾经有一份不甘心,也因为这个才有了我和传智播客、黑马程序员的缘分,这次参加阿里社招面试首先是大学同学内推的,他在阿里天猫做大数据的,有内推的名额。经过十多天的艰辛历程,最后终于啃下了阿里的offer,这对我来讲十分有意义,校招的时候因为没有一点的android基础倒在了技术二面,去了深圳黑马苦练一番,然后经过一年工作时间的积累,最终还是达成目标,心满意足了。不扯皮了,下面整点硬菜了

1. 面试情况



【面试公司】阿里巴巴集团天猫事业部
【面试结果】拿到offer(16K+五险一金+年终奖)
【面试时间】2016/3/29 -- 2016/4/5


2. 笔试题目

        由于参加的是在线笔试的缘故,下面题目全部凭印象记得,有些题百度找到了原型,有些就只能记个大概了。

       1、设有一个顺序栈S,元素s1、s2、s3、s4、s5、s6依次进栈,如果6个元素的出栈顺序为s2、s3、s4、s6、s5、s1,则顺序栈的容量至少应为多少?
       A、2                      B、3                             C、4                           D、5

       2、给定如下代码: int x[4]={0}; int y[4]={1}; 数组x和y的值为()
              A、{0,0,0,0},{1,1,1,1}
              B、{0,0,0,0},{1,0,0,0}
              C、{0,不确定},{1,不确定}
               D、与编译器相关

        3、假设在n进制下,下面的等式成立,n值是() 567*456=150216
             A、9           B、10            C、12          D、18

        4、在排序方法中,元素比较次数与元素的初始排列无关的是()
            A、Shell 排序     B、归并排序    C、直接插入排序    D、选择排序

        5、(he)的平方=she。h、e、s代表的数字?分别代表2、5、6

       6、一个完全二叉树有770个节点,那么其叶子的个数为:385

       7、 2的32次方是多少?
      解答:这个题目我当时不知道咋写,最后用二进制表示了。
              100000000000000000000000000000000

        8、假如已知有n个人和m对好友关系(存于数字r)。如果两个人是直接或间接的好友(好友的好友的好友...),则认为他们属于同一个朋友圈,请写程序求出这n个人里一共有多少个朋友圈。假如:n = 5 , m = 3 , r = {{1 , 2} , {2 , 3} , {4 , 5}},表示有5个人,1和2是好友,2和3是好友,4和5是好友,则1、2、3属于一个朋友圈,4、5属于另一个朋友圈,结果为2个朋友圈。
       解答:这个题目属于数据结构中并查集的应用,不懂并查集的可以找度娘帮忙!
  1. public class Test {
  2.         private int[] set = new int[1000];
  3.         public int find(int x) { // 带路径优化的并查集查找算法
  4.                 int i, j, r;
  5.                 r = x;
  6.                 while (set[r] != r)
  7.                         r = set[r];
  8.                 i = x;
  9.                 while (i != r) {
  10.                         j = set[i];
  11.                         set[i] = r;
  12.                         i = j;
  13.                 }
  14.                 return r;
  15.         }
  16.         public void merge(int x , int y){    //优化的并查集归并算法
  17.             int t = find(x);
  18.             int h = find(y);
  19.             if(t < h)
  20.                 set[h] = t;
  21.             else
  22.                 set[t] = h;
  23.         }
  24.         int friends(int n , int m , int[][] r){
  25.                 int i , count;
  26.                 for(i = 1 ; i <= n ; ++i)    //初始化并查集,各点为孤立点,分支数为n
  27.                         set[i] = i;
  28.                 for(i = 0 ; i < m ; ++i)
  29.                         merge(r[i][0] , r[i][1]);
  30.                 count = 0;
  31.                 for(i = 1 ; i <= n ; ++i)
  32.                 {
  33.                         if(set[i] == i)
  34.                                 count++;
  35.                 }
  36.                 return count;
  37.         }
  38.         public static void main(String[] args) {
  39.                 System.out.println(new Test().friends(5, 3, new int[][]{{1,2},{2,3},{4,5}}));
  40.         }
复制代码

  9、ID为TMao的淘宝用户前些日子在淘宝机器人网店购买了一个智能机器人oz.这个机器人不仅精致小巧,还具有很多有意思的功能。比如:oz可以在迷宫里自由的上下左右走动; 并且,在不碰到障碍物的情况下,它能够以最短时间从入口处走到出口 (假设存在的话); 最智能的是,在有充电器的地方oz还可以给自己充电 。
现在,TMao设计了很多种迷宫,并且在里面随意的摆了些充电器,想请你们帮他算下,这个智能机器人要多久时间可以走出去呢?
他做了如下假设:
       1.迷宫可以看作是长为w,宽为h的网格;
       2.机器人每移动一步,需要时间1s,消耗电量0.5格;
       3.机器人初始电量为满格4格;
      4.每个充电器充电次数不限 (充电时间所需时间忽略不计),机器人可以反复经过一个地方,但是不能走到有障碍的地方,并且一旦机器人电量变为0,它就只能停下来,哪怕这个位置正好有充电器,它也没有足够的电量去执行充电操作;
       5.机器人走到迷宫出口,必须至少还有0.5格电量,否则也算没走出出口。
输入:
第一行输入w,h分别表示迷宫的长和宽(w , h <= 10)。
接下来的h行表示迷宫的布局:-1表示该位置是障碍物, 0表示该位置什么也没有,1表示迷宫入口, 2表示迷宫出口, 3表示该位置有充电器。
输出:
输出机器人oz走到出口处的时间;如果无法按要求走到出口则输出”Pity oz!”。
     
        解答:这种类似题目我之前就写过很多,这道题属于图论里的搜索问题,不过他加了一些限制条件。就是每次到了一个新的充电地方就可以以饱满的电量继续前进。所以就先从起点开始找。每次到了一个充电点且比以前的路劲更优的话就可以更新路径。把这个点继续入队列,下一次又从这一个点开始BFS(广度优先搜索)。直到全部搜索完毕,这题要用到优先队列,当时对java的优先队列还不熟悉,直接用了C++ STL模板库了,所以下面是c++代码,不过差不多都一样。

  1. #include<cstdio>  
  2.     #include<cstring>  
  3.     #include<cstdlib>  
  4.     #include<queue>  
  5.     using namespace std;  
  6.     int map[13][13];  
  7.     int minpath[13][13]; //用来存放从原点到这一步i,j的最小步数。  
  8.     int row,col;  
  9.     int endi,endj;  
  10.     int dir[][2] = {{-1,0},{0,-1},{1,0},{0,1}};  
  11.     struct node  
  12.     {  
  13.         int x,y;  
  14.         int pu;   //真正的步数  
  15.         int p;      //电池的数字用1~7表示  
  16.         bool operator < (const node& a)const
  17.         {  
  18.             return p>a.pu;  
  19.         }      
  20.     };      
  21.     priority_queue<node> pq;  //优先队列必不可少,  
  22.     int Min(int a,int b)  
  23.     {  
  24.         return a>b?b:a;  
  25.     }  
  26.     void BFS(struct node no)  
  27.     {  
  28.         queue <node> q;  
  29.         q.push(no);  
  30.         struct node var;  
  31.         while(!q.empty())  
  32.         {  
  33.             no = q.front();  
  34.             q.pop();  
  35.             if(map[no.x][no.y]==2)  
  36.                 minpath[no.x][no.y] = Min(minpath[no.x][no.y],no.pu);  
  37.             if(map[no.x][no.y]==3 && no.pu<minpath[no.x][no.y])//每次找到充电点还要判断他是否是比上一次更优  
  38.             {  
  39.                 minpath[no.x][no.y] = no.pu;  
  40.                 var = no;  
  41.                 var.p = 0;          //每次找到一个充电点就把充电归零  
  42.                 pq.push(var);       //每次找到一个充电点就要把它入队列。。核心核心  
  43.             }  
  44.             for(int i=0;i<4;i++)  
  45.             {  
  46.                 int x = no.x+dir[i][0];  
  47.                 int y = no.y+dir[i][1];  
  48.                 if(map[x][y]!=-1 && no.p<7)  //不能到7,到7就是只有0.5电量,不能进行下一步了  
  49.                 {  
  50.                     var.x = x;  
  51.                     var.y = y;  
  52.                     var.pu = no.pu+1;  
  53.                     var.p = no.p+1;  
  54.                     q.push(var);  
  55.                 }  
  56.             }  
  57.         }  
  58.     }      
  59.     int main()  
  60.     {  
  61.         int i,j;  
  62.         while(scanf("%d%d",&col,&row) && row+col!=0)  
  63.         {  
  64.             struct node no;  
  65.             memset(map,-1,sizeof(map));  
  66.             memset(minpath,0x3f,sizeof(minpath));  
  67.             while(!pq.empty())  
  68.                 pq.pop();  
  69.             for(i=1;i<=row;i++)  
  70.             for(j=1;j<=col;j++)  
  71.             {  
  72.             scanf("%d",&map[i][j]);  
  73.             if(map[i][j]==1)  
  74.             {  
  75.             no.x = i;  
  76.             no.y = j;  
  77.             no.p = no.pu = 0;  
  78.             pq.push(no);  
  79.             }  
  80.             if(map[i][j]==2)  
  81.             {  
  82.                 endi = i;  
  83.                 endj = j;  
  84.             }  
  85.             }  
  86.             while(!pq.empty())   
  87.             {  
  88.                 no = pq.top();  
  89.                 pq.pop();  
  90.                 BFS(no);     
  91.             }  
  92.             if(minpath[endi][endj]!=minpath[0][0]) //minpath[0][0]一直没有变化,所以和它比  
  93.             printf("%d\n",minpath[endi][endj]);  
  94.             else
  95.                 printf("Pity oz!\n");  
  96.         }      
  97.         return 0;  
  98.     }      
复制代码

10、假设有一个硬币,抛出字(背面)和花(正面)的概率都是0.5,而且每次抛硬币与前次结果无关。现在做一个游戏,连续地抛这个硬币,直到连续出现两次字为止,问平均要抛多少次才能结束游戏?注意,一旦连续抛出两个“字”向上游戏就结束了,不用继续抛。
         解答:这题目当时我也是搞了半天一点头绪没有,事后在网上找到了答案(数学不好的建议忽略不看,保智商要紧)
         点击查看答案 http://www.cnblogs.com/atyuwen/archive/2010/09/12/coin.html

3. 面试经过

        刚开始都是互相介绍一下,问了我一些个人问题,这里就不多说了,直接进入正题!

        Q: 按照简历你毕业才半年多的时候,怎么工作年限你写的1年呢?
        A: 是这样的,当初阿里校招的时候我也应聘Android开发,但因为没有一点开发经验,二面就被刷了,之后自己自学了一段Android时间,就去深圳进入泰捷公司,在泰捷的一年我觉得自己成长了很多,学到了很多Android开发技巧,掌握了主流Android的开发技术。但去阿里这个大平台学习和发展一直是我的梦想,所以当我觉得自己技术可行的时候,我就再次来试试了。

         Q: 你项目里面提到了应用Glide图片加载框架,能详细叙述一下吗?
         A:现在的Android开发中主流的图片加载框架主要有Glide、Picasso、Fresco等,当然也存在一些比较老的框架如Universal-ImageLoader、XUtils等。其实Picasso这个库我用的时间最长,它有以下特性:
  • 处理Adapter中的 ImageView 回收和取消已经回收ImageView的下载进程
  • 使用最少的内存完成复杂的图片转换,比如把下载的图片转换为圆角等
  • 自动添加磁盘和内存缓存
而Gilde是在最近的一个项目中用到的,但我对它也是比较熟悉的了,Glide具有获取、解码和展示视频剧照、图片、动画等功能,它还有灵活的API,这些API使开发者能够将Glide应用在几乎任何网络协议栈里。Glide可以实现平滑的图片列表滚动效果,支持远程图片的获取、大小调整和展示。15年的时候,Glide 3.0发布,这个版本包括很多新功能,如
  • 支持Gif 动画和视频剧照解码;
  • Activity 与Fragment生命周期的集成,可以智能的暂停和重新开始请求;
  • 支持缩略图;
  • OkHttp 和Volley 的支持等,Glide默认选择HttpUrlConnection作为网络协议栈,当然我们也还可以选择OkHttp和Volley作为网络协议栈;

最后还有一个Fresco,它是FaceBook主推的图片加载框架。我在平时学习中应用过,但项目中还未具体应用。它实现了图片的渐进式呈现,渐进式的JPEG图片格式已经流行数年了,渐进式图片格式先呈现大致的图片轮廓,然后随着图片下载的继续,呈现逐渐清晰的图片,这对于移动设备,尤其是慢网络有极大的利好,可带来更好的用户体验,同时它也支持对Gif图和WebP格式图的加载。

       Q:你刚才提到了OKHttp,你对OKHttp有什么了解,做过okhttp的封装吗?
       A:我负责开发的游戏中心,网络请求框架用的就是Volley+OkHttp,Volley 默认根据 Android 系统版本使用不同的 Http 传输协议实现.在 Android 2.3以下使用 ApacheHttpStack 作为传输协议, 在 3.0 及以下使用 HttpURLConnection 作为传输层协议。而OkHttp 相较于其它的实现有以下的优点.
  • 支持SPDY,允许连接同一主机的所有请求分享一个socket。
  • 利用响应缓存来避免重复的网络请求。
  • 当网络出现问题的时候,OKHttp会依然有效,它将从常见的连接问题当中恢复。
  • 如果服务端有多个IP地址,当第一个地址连接失败时,OKHttp会尝试连接其他的地址,这对IPV4和IPV6以及寄宿在多个数据中心的服务而言,是非常有必要的。

因此使用 OkHttp 作为替代是好的选择.使用也非常简单,首先用 OkHttp 实现一个新的 HurlStack 用于构建 Volley 的 requestQueue. 然后使用 OkHttpStack 创建新的 Volley的 requestQueue.即可。

      Q:简历上你写的熟悉c/c++,但你是做Android开发的,应该对java更熟悉吧?
      A:是这样的,我大学主要学的c和c++,用来搞Acm的,毕业之后虽然一直在从事Android开发,但每周都会抽时间去刷刷题,用的就是c/c++。相比较而言,现在可能对java更熟悉,其实使用哪种开发语言都不是很重要,重要的是掌握解决问题的思想,因为搞过Acm,所以特别喜欢琢磨问题。刚开始做项目的时候,在项目开发中常会用到一些第三方框架,但我不会直接拿来使用,一般都是先学习别人框架的思想和代码,然后写出自己的工具类,并分享出去,比如Andorid的图片加载三级缓存(内存、本地、网络),内存缓存用到了LruCache,这个类内部实现了对BitMap的LRU算法管理,我参考了LruCache类,用LRU算法对本地磁盘的图片数据也进行了管理。之后才发现,原来国外大牛早已经写了DiskLruCache类,又拿过来学习了一番,收获颇多。

       大的问题就这几个,我面试有个习惯,喜欢把一个技术点做深度剖析,而这一点很迎合大公司对面试者技术点考察要求,几个问题过后,面试官就不在发难提问了,面试话题也从开始的技术提问转移到国内直播平台的讨论,屌丝间的话题大家都懂,挺High的。

4. 面试总结
            
      大公司真是不给活路啊,怎么社招都这么变态的,对于应聘者的编程基础要求很高,不过也符合大公司对技术人员的要求。所以,各位童鞋们,加油吧!

                                                                                    


3 个回复

倒序浏览
好棒,支持
回复 使用道具 举报
好棒,支持一下
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马