zoukankan      html  css  js  c++  java
  • 美团网2014-9-26专访(侧长沙)

        我收到了美团网笔试时间2014年9一个月24号湖进行测试,写关于这个问题我刚才看到有点害怕,我的手推掉,你们是算法主题的类型,外观似我们使用c书面。而且我已经很长时间没有实用c编写的代码,要说算法了。算法也仅仅有大一的时候做了点acm的题目。就那点底子也早就忘了,顿时我的心就有点慌了。

    深深的吸了口气,稳定下心来。安慰自己,怕什么了,来都来了,跑的累死了。反正死猪不怕开水烫。于是就開始动手答题了。如今仅仅模糊的记得几道笔试的题目了。例如以下:

    1。求把一个字符串转换成整数。转换出错。则返回0。大概意思是这样吧。

              我想到的的解决的方法是,把每个字符提取出来,比方'9',字符'9'-'0'字符9减去字符0就是所相应的数字了(数字加'0'就得到相应的数字字符)。

    把得到的数字化成sum=sum*10+num;sum是累加的和,num是字符相应的数字,開始sum为0.


    2.构造一个函数把一个整数从高位到低位。比方123。存储到单链表中,比方第一个结点存1,第二个结点存2,第3个结点存3,函数返回单链表的头指针;构造函数把前面的单链表乘个位数(0-9),把结果存到单链表中。

         对于第一步,我想到的解决的方法是






              做完笔试后,自我感觉还行吧。想应该过了。

    回来后,快晚上12点了,我一个同学跟我说。他收到了电话,说叫他明天去面试,问我收到没,我说没收到啊,心有点凉了操心自己没过了。一直到第二天上午11点才收到美团姐姐给我的电话,通知第二天去面试。心情瞬间有点小激动了,因这是我第一次正式面试,处女面啊。能不激动嘛?(在之前有一个阿里的面试在武汉,太远了。又认为没得多大的希望,就没浪费钱去面试了。)

             上面说了点笔试的题目,如今进入正题吧,说下我的一面:

    我选择的面试时间是下午1点半,地点是中南科教南楼,由于我要赶车,所以去的比較的早,在教室歇息了下了。快1点的时候開始往面试的地方走去,中间遇到了一个湖大的,专门是搞算法的,貌似非常厉害,后来了解到,他面试过百度,阿里,腾讯,至少比我厉害吧。我笔试都没过,我不是搞算法的。还面试了cvte,进了3面,听说cvte耍人挺严重,10几万人仅仅招300多人。貌似有点坑。后来去签了到。在一个教室里面等面试,我是第二批进去的,进去时候。没有空暇的面试管,一个hr姐姐,叫我等下,就仅仅能等下了。后来给我面试的时一位帅哥,看起来还蛮和蔼的。我走过去,開始拿出草稿本和笔,准备面试(认为有点遗憾的,成绩单和一些荣誉证书拿去了。没拿出来。)。

    面试官哥哥開始让我做下自我介绍。。

    。我就皮拉啪啦说了下,当中他做了下笔记。然后就正式的问我问题了。


      1.你说说这笔试题目难?

             这问题答的不太好。我说笔试都是算法和c语言的题目,而我已经非常久么碰过c了,所以有点难度。后来问我学什么的,我说是学java的,有问了我是想搞后台开发还是android开发,这里回答认为有非常大的问题,我就不说了,我应该肯定说是搞android开发的。



      2.java的反射机制。

         反射主要是指程序能够訪问,检測和改动它本身的状态或行为的一种能力。

    java中反射是一种强大的工具。它可以创建灵活的代码。这些代码可以在执行时装载。无须在组件之间进行链接。反射同意在编写与执行时。使程序可以接入到jvm中的类的内部信息,而不是源码中选定的类协作的代码。这使反射成为构建灵活应用代码的主要工具。须要注意的是,假设使用不当,反射的成本会非常高。

    具体内容參照:http://blog.csdn.net/j903829182/article/details/38405735



      3.数据库的隔离机制。什么是乐观锁。悲观锁,有什么差别。

        

    1. 数据库提供了4中隔离级别:  
    2. 隔离级别    描写叙述  
    3. READ UNCOMMITTED(读未提交数据)    同意事务读取未被其它事务提交的变更。脏读、不可反复读和幻读的问题都会出现  
    4. READ COMMITED(读已提交数据)   仅仅同意事务读取已经被其它事务提交的变更,能够避免脏读。但不可反复读和幻读问题仍然会出现  
    5. REPEATABLE READ(可反复读)   确保事务能够多次从一个字段中读取同样的值,在这个事务持续期间,禁止其它事务对这个字段进行更新,能够避免脏读和不可反复读,但幻读的问题依旧存在  
    6.   
    7. SERIALIZABLE(串行化)   确保事务能够从一个表中读取同样的行。在这个事务持续期间,禁止其它事务对该表运行插入、更新和删除操作。全部并发问题都能够避免,但性能十分低  

    1. Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE. Oracle 默认的事务隔离级别为: READ COMMITED   
    2. Mysql 支持 4 种事务隔离级别. Mysql 默认的事务隔离级别为: REPEATABLE READ  


        具体的请參照:http://blog.csdn.net/aigoleague/article/details/8181594

                                  http://blog.csdn.net/w_l_j/article/details/7354530


    导读:

    事务:是构成单一逻辑工作单元的操作集合。要么完整地运行,要么全然不运行。

    数据库事务的ACID性质:

         原子性:一个事务对数据库的所有操作,是一个不可切割的工作单元,这些操作要么所有运行。要么什么也不做。

         一致性:一个事务独立运行的结果。应保持数据库的一致性,即数据库不会因事务的运行而遭受破坏。

        隔离性:多个事务并发运行时。系统应保证与这些事务先后单独运行时的结果一样,此时事务达到隔离性要求。

        持久性:一个事务一旦完毕所有操作后,它对数据库的所有更新应永久地反映在数据库中,不会丢失。

      

    数据库并发带来的3个问题:

        丢失更新。读脏数据问题,不可反复读问题。

        丢失更新问题:简单的理解,数据更新错误

          读脏数据问题:在数据库技术中,把未提交的随后被撤销的数据称为脏数据。easy引起自身更新操作被丢失。破坏了数据库的完整性。

          不可反复读:t1须要2次读取同一项数据项a,可是在两次读操作的间隔中,还有一个事务t2改变了a的值。因此。t1在2次读同一项数据a时却读出不同的值。


    锁分为排他锁和共享锁:

         排他锁简称X锁又称写锁,假设事务t对某个数据r(能够是数据项,记录,数据集乃至整个数据库)实现了X锁,那么在t对数据r解除锁之前。不同意其它事务t在对该数据加不论什么类型的锁。

        共享锁简称S锁,有称为读锁:假设事务t对某数据加S锁后,仍同意其它事务在对该数据加S锁,可是在对该数据的全部S锁都解除之前绝不同意不论什么事务对该数据加X锁。

    这样的锁成为S锁。


    可串行话的概念:每一个事务中,语句的先后顺序在各种调度中始终保持一致。在这个前提下,假设一个并发调度的运行结果与一串行调度的运行结果等价,那么这个并发调度称为“可串行化的调度”,否则是不可串行话的调度。



    事务提供的4种隔离级别:

        READ   UNCOMMITED(能够读未提交的数据):同意事务读已提交或未提交的数据。

        READ  COMMITED(读提交数据):同意事务读已提交的数据,但不要求“可反复读”。

    比如,事务对同一记录的两次读取之间,记录可能被已提交的事务更新。

        REPEATABLE  READ(可反复读):仅仅同意事务读已提交的数据,而且在两次读同一数据时不同意其它事务改动此数据。

        SERIALIZABLE(可串行话):同意事务与其它事务并发运行。但系统必须保证并发调度是可串行化的,不致错误发生。


          可參考博客:http://blog.csdn.net/sdyy321/article/details/6183412

           

           悲观锁会完毕下面功能:锁住读取的记录,防止其他事务读取和更新这些记录。其他事务会一直堵塞。直到这个事务结束。悲观锁是在使用了数据库的事务隔离功能的基础上。独享占用的资源。以此保证读取数据一致性。避免改动丢失。

              乐观锁不会锁住不论什么东西,也就是说,它不依赖数据库的事务机制。乐观锁全然是应用系统层面的东西。

    假设使用乐观锁,那么数据库就必须加版本号字段,否则就仅仅能比較全部字段。但由于浮点类型不能比較,所以实际上没有版本号字段是不可行的。



      4.什么是进程,什么是线程。进程和线程的差别。

     

    进程是具有一定独立功能的程序关于某个数据集合上的一次执行活动,进程是系统进行资源分配和调度的一个独立单位.  
    线程是指进程内的一个运行单元,也是进程内的可调度实体.
    与进程的差别:
    (1)地址空间:进程内的一个运行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;
    (2)资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
    (3)线程是处理器调度的基本单位,但进程不是.
    4)二者均可并发运行. 



      5.问我用了什么浏览器,浏览器打开一个新的标签页面的时候是用的进程还是线程。

            我回答错了。正确的应该是,看是什么浏览器,不同的浏览器,实现的方法有些不同。有的是用的多进程,有的是共用以个进程。比方谷歌浏览器,打开一个标签就是一个新的进程,可是也能够设置使用单进程,即全部的标签共用一个进程。有的浏览器使用的是单进程。

    多进程提高了整个应用的稳定性:倘若有一个标签页崩溃、假死了,并不会影响到其它的标签页。

    多进程能够提高应用总体性能:如今计算机已经进入多核时代,仅仅有能利用多个核心的优势才干进一步提高程序性能。一般而言,单进程的程序要通过线程来利用多核,可是线程之间因为共享同一片内存地址,编写代码easy出现故障,不如传统的进程方式方便稳定。 



      6.字符串有什么匹配算法。kmp算法的时间复杂度,你可以写一个kmp算法嘛?

            字符串匹配算法有。Brute-Force算法和KMP算法。kmp算法的时间复杂度是O(n+m)

           详细的能够參考:http://blog.csdn.net/j903829182/article/details/37885359



      7.问我知道什么排序算法。

             详细的能够參考我写的排序算法总结:http://blog.csdn.net/j903829182/article/details/38018507


      8.写一个堆排序。

    能够參考:http://blog.csdn.net/j903829182/article/details/38018507

    1. /* 
    2. 1.堆排序分为最大堆(也称大顶堆或大根堆)和最小堆(也称小顶堆或小根堆) 
    3. 2.最大堆的定义:设数组a中存放了n个数据元素,数组下标从0開始,假设当数组下标2i+1<n时有 
    4.   a[i].key>=a[2i+1].key,当数组下标2i+2<n时有a[i].key>=a[2i+2].key,则这种数据结构称为最大堆 
    5.  
    6. 3.最小堆的定义:设数组a中存放了n个数据元素,数组下标从0開始,假设当数组下标2i+1<n时有 
    7.   a[i].key<=a[2i+1].key,当数组下标2i+2<n时有a[i].key<=a[2i+2].key,则这种数据结构称为最小堆 
    8.  
    9. 4.最大堆的根结点是堆中值最大的数据元素,最小堆的根节点是堆中值最小的数据元素。对于最大堆。从根结点到每一个叶节点 
    10.   的路径上。数据元素组成的序列都是递减有序的。对于最小堆,从根结点到每一个叶节点的路径上,数据元素组成的序列都是递增有序的。 
    11. 5.堆排序的基本思想:首先把n元素的数组a初始化创建为最大堆,然后循环运行例如以下过程直到数组为空为止: 
    12.   a.把堆顶a[0]元素(为最大元素)和当前最大堆的最后一个元素交换; 
    13.   b.最大堆元素个数减1; 
    14.   c.因为第a步后根节点不再满足最大堆的定义,所以调整根结点使之满足最大队的定义。

       

    15. 6.堆排序算法的时间复杂度为O(nlbn),堆排序的空间复杂度为O(1),堆排序是一种不稳定的排序算法 
    16. */  
    17.   
    18. void CreateHeap(DataType a[],int n,int h){  
    19. //调整非叶结点a[h]使之满足最大堆。n为数组a的元素个数  
    20.     int i,j,flag;  
    21.     DataType temp;  
    22.     i=h;//i为要创建堆的二叉树根节点  
    23.     j=2*i+1;//j为i的左孩子节点的下标  
    24.     temp=a[i];  
    25.     flag=0;  
    26.     //沿左右孩子中值较大者反复向下筛选  
    27.     while(j<n&&flag!=1){  
    28.       
    29.         //寻找左右孩子节点中的较大者,j为其下标  
    30.         if(j<n-1&&a[j].key<a[j+1].key){  
    31.           
    32.             j++;  
    33.         }  
    34.   
    35.         if(temp.key>a[j].key){//a[i].key.key>a[j].key  
    36.           
    37.             flag=1;//标志结束筛选条件  
    38.         }else{//否则把a[j]上移  
    39.           
    40.             a[i]=a[j];  
    41.             i=j;  
    42.             j=2*i+1;  
    43.         }  
    44.     }  
    45.     a[i]=temp;  
    46. }  
    47.   
    48. void InitCreatHeap(DataType a[],int n){  
    49. //把数组元素a[0]--a[n-1]初始化创建为最大堆  
    50.     int i;  
    51.     for(i=(n-2)/2;i>=0;i--){  
    52.         CreateHeap(a,n,i);  
    53.     }  
    54. }  
    55.   
    56.   
    57. //堆排序算法函数例如以下  
    58. void HeapSort(DataType a[],int n){  
    59. //用堆排序法对数组元素a[0]--a[n-1]进行排序  
    60.     int i;  
    61.     DataType temp;  
    62.     InitCreatHeap(a,n);//初始化创建最大堆  
    63.     for(i=n-1;i>0;i--){//当前最大堆个数每次递减1  
    64.         //把堆顶a[0]元素和当前最大堆的最后一个元素交换  
    65.         temp=a[0];  
    66.         a[0]=a[i];  
    67.         a[i]=temp;  
    68.   
    69.         CreateHeap(a,i,0);//调整根结点满足最大堆  
    70.         //注意此时二叉树根结点下标为0。子二叉树结点个数为i  
    71.     }  
    72.   
    73. }  

    堆排序比較的复杂,我写的时候,写错了。我自己都不知道写的是什么了。。。。

    汗啊。。





      9.一个单链表a->b->c->d->e........->y->z,奇数不变,偶数符号变。转换成a->b<-c->d<-............x<-y->z

            这题的代码,就略了,我就说下思想吧!!!

    ,本来我以为按a->b<-c->d<-............x<-y->z输出就能够了。可是最后面试官说要返回一个这种单链表,汗。。难道我理解错了,可是他说的时候仅仅说了一个节点里面仅仅有一个存数据。一个存下一个节点的指针,那箭头存哪了????好吧,要是理解对了。我也就能够写出来了。。。。

            思想:

             遍历单链表,推断是否是偶节点,是偶节点的话,就把节点里面的箭头变化下,最后函数返回头指针




      10.单链表逆序比方a->b->c->d->e....->y->z。变成z->y->x..........->c->b->a

            思想:用一个指针指向该单链表,单链表本身的指针指向NULL,遍历新的单链表,取出新的每个节点。并把它插入到原来头指针向的第一个节点前面,最后返回头指针。这样就能够实现逆序了。



      11.一个概率问题,一个色子6面,正常情况下每面出现的概率是1/6,如今要设计一个游戏。色子是不均匀的。其每面出现的概率都不在是1/6,并且每面出现的概率不一样,怎么设计这个游戏使输赢都是1/2。




      12.一枚硬币2面,不均匀的,所以正面朝上和反面朝上的概率都不是1/2,如今设计一个游戏,使输赢都是1/2.

              參考:http://page.renren.com/601495586/note/869560088

              

    问题描写叙述:有一枚不均匀的硬币,已知抛出此硬币后,正面向上的概率为p(0 < p < 1)。请利用这枚硬币产生出概率相等的两个事件。

    这个问题跟之前的利用等概率Rand5产生等概率Rand3很像。但却简单的多。几个月前还为这个事情头疼了一下,如今想来真是不应该。

    某一次抛出硬币,正面向上的概率是p。反面向上的概率是1 - p,当p不等于0.5时,这两个事件的概率就不一样了。怎么能凑出等概率呢?还是要利用概率的加法和乘法法则。这里用乘法,也就是连续的独立事件。

    连续抛两次硬币,正反面的出现有四种情况,概率依次为:

    1. 两次均为正面:p * p
    2. 第一次正面,第二次反面:p * (1 - p)
    3. 第一次反面。第二次正面:(1 - p) * p
    4. 两次均为反面:(1 - p) * (1 - p)

    这不。中间两种情况的概率是全然一样的。

    于是问题的解法就是连续抛两次硬币,假设两次得到的同样则又一次抛两次;否则依据第一次(或第二次)的正面反面情况,就能够得到两个概率相等的事件。

      13.git的pull命令。怎么克隆。与克隆的差别。


    git clone git库地址                                 克隆到本地

    git pull把最新的提交从远程抓取下来到本地。 git pull:相当于是从远程获取最新版本号并merge到本地



      14.git创建分支,切换分支。列出全部的分支。

    首先。我们创建dev分支。然后切换到dev分支:

    $ git checkout -b dev

    git checkout命令加上-b參数表示创建并切换,相当于下面两条命令:

    $ git branch dev
    $ git checkout dev

    然后,用git branch命令查看当前分支:

    $ git branch
    * dev
      master
    

    git branch命令会列出全部分支。当前分支前面会标一个*号。


    合并分支:

    $ git merge dev
    git merge命令用于合并指定分支到当前分支


    合并完毕后,就能够放心地删除dev分支了:

    $ git branch -d dev


    查看分支:git branch

    创建分支:git branch name

    切换分支:git checkout name

    创建+切换分支:git checkout -b name

    合并某分支到当前分支:git merge name

    删除分支:git branch -d name



    本文原创:转载请注明来自:http://blog.csdn.net/j903829182/article/details/39587253
















































    版权声明:本文博主原创文章。博客,未经同意不得转载。

  • 相关阅读:
    通过 INotifyPropertyChanged 实现观察者模式(转)
    Asp.net MVC中的ViewData与ViewBag(转)
    FireFox地址栏百度搜索
    ZigBee设备类型
    Array.prototype.slice.call(arguments) (转)
    泛型方法扩展
    定义IE的文档兼容模式
    C# Lazy<T>(转)
    AutoCAD2010/2012去掉搜索框
    python 集合类型
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4856057.html
Copyright © 2011-2022 走看看